Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions gradle/scripts/moddevgradle.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ neoForge {
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}

clientEnforceLegacyBuffers {
client()
systemProperty "anvilcraft.enforceLegacyBuffers", "true"
}

server {
server()
programArgument '--nogui'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.client.renderer.Line;
import dev.dubhe.anvilcraft.client.support.PowerGridSupport;
import dev.dubhe.anvilcraft.util.ColorUtil;
import dev.dubhe.anvilcraft.util.Line;
import dev.dubhe.anvilcraft.util.ShapeUtil;
import dev.dubhe.anvilcraft.util.VirtualThreadFactoryImpl;
import lombok.Getter;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package dev.dubhe.anvilcraft.api.rendering.foundation;

import dev.dubhe.anvilcraft.api.rendering.foundation.buffer.vertex.GlVertexBuffer;
import dev.dubhe.anvilcraft.api.rendering.foundation.buffer.vertex.QuadSortingState;
import lombok.EqualsAndHashCode;
import net.minecraft.client.renderer.RenderType;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import org.lwjgl.system.MemoryUtil;

@EqualsAndHashCode
public final class CompileResult implements Disposable {
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
private final RenderType renderType;
private final int vertexCount;
private final int vertexSize;
private final long vertexBufferPtr;
private final int indexCount;
@Nullable
private final QuadSortingState sortingState;
private boolean freed = false;

public CompileResult(
RenderType renderType,
int vertexCount,
int vertexSize,
long vertexBufferPtr,
int indexCount,
@Nullable QuadSortingState sortingState
) {
this.renderType = renderType;
this.vertexCount = vertexCount;
this.vertexSize = vertexSize;
this.vertexBufferPtr = vertexBufferPtr;
this.indexCount = indexCount;
this.sortingState = sortingState;
}

public void upload(GlVertexBuffer vertexBuffer) {
vertexBuffer.upload(vertexBufferPtr, vertexCount * vertexSize, vertexCount, indexCount, sortingState, new Vector3f(), this);
}

public void dispose() {
if (freed) return;
ALLOCATOR.free(vertexBufferPtr);
freed = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.dubhe.anvilcraft.api.rendering.foundation;

public interface Disposable {
/**
* It is guaranteed to run on Render Thread.
*/
void dispose();
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
package dev.dubhe.anvilcraft.api.rendering;
package dev.dubhe.anvilcraft.api.rendering.foundation;

import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.VertexBuffer;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormat;
import dev.dubhe.anvilcraft.api.rendering.foundation.buffer.vertex.GlVertexBuffer;
import dev.dubhe.anvilcraft.api.rendering.foundation.buffer.vertex.QuadSortingState;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMaps;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import lombok.Getter;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import org.lwjgl.system.MemoryUtil;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.concurrent.ConcurrentHashMap;

@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class FullyBufferedBufferSource extends MultiBufferSource.BufferSource implements AutoCloseable {
public class FullyBufferedBufferSource extends MultiBufferSource.BufferSource implements Disposable {
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
private final Map<RenderType, ByteBufferBuilder> byteBuffers = new HashMap<>();
private final Map<RenderType, BufferBuilder> bufferBuilders = new HashMap<>();
final Reference2IntMap<RenderType> indexCountMap = new Reference2IntOpenHashMap<>();
private final Map<RenderType, ByteBufferBuilder> byteBuffers = new ConcurrentHashMap<>();
private final Map<RenderType, BufferBuilder> bufferBuilders = new ConcurrentHashMap<>();
@Getter
private final Reference2IntMap<RenderType> indexCountMap = Reference2IntMaps.synchronize(new Reference2IntOpenHashMap<>());

public FullyBufferedBufferSource() {
super(null, null);
Expand All @@ -50,12 +53,9 @@ public boolean isEmpty() {
public void endBatch(RenderType renderType) {
}

public void upload(
Function<RenderType, VertexBuffer> vertexBufferGetter,
Consumer<Runnable> runner
) {
public void upload(CompileContext context) {
for (RenderType renderType : bufferBuilders.keySet()) {
runner.accept(() -> {
context.submitUploadTask(() -> {
BufferBuilder bufferBuilder = bufferBuilders.get(renderType);
ByteBufferBuilder byteBuffer = byteBuffers.get(renderType);
long ptr = byteBuffer.pointer;
Expand All @@ -64,19 +64,23 @@ public void upload(
long allocated = ALLOCATOR.malloc(compiledVertices);
MemoryUtil.memCopy(ptr, allocated, compiledVertices);
MeshData mesh = bufferBuilder.build();
if (mesh != null) {
mesh.close();
if (mesh == null) return;
QuadSortingState state = null;

if (renderType.sortOnUpload) {
state = QuadSortingState.fromMesh(mesh);
}
mesh.close();
CompileResult compileResult = new CompileResult(
renderType,
bufferBuilder.vertices,
renderType.format.getVertexSize(),
allocated,
renderType.mode.indexCount(bufferBuilder.vertices)
renderType.mode.indexCount(bufferBuilder.vertices),
state
);
indexCountMap.put(renderType, renderType.mode.indexCount(bufferBuilder.vertices));
compileResult.upload(vertexBufferGetter.apply(renderType));
compileResult.free();
compileResult.upload(context.getOrCreateBuffer(renderType, mesh.drawState().indexType()));
}
byteBuffer.close();
bufferBuilders.remove(renderType);
Expand All @@ -90,7 +94,13 @@ public void close(RenderType renderType) {
builder.close();
}

public void close() {
public void dispose() {
byteBuffers.keySet().forEach(this::close);
}

public interface CompileContext {
GlVertexBuffer getOrCreateBuffer(RenderType renderType, VertexFormat.IndexType indexType);

void submitUploadTask(Runnable runnable);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.dubhe.anvilcraft.api.rendering.foundation;

import dev.dubhe.anvilcraft.api.rendering.foundation.buffer.vertex.QuadSortingState;
import it.unimi.dsi.fastutil.ints.IntArrays;
import org.joml.Vector3f;

public class QuadSorter {
public static int[] buildSortedIndexByDistance(QuadSortingState state, Vector3f point){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Checkstyle] <com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck> reported by reviewdog 🐶
WhitespaceAround: '{' is not preceded with whitespace.

float[] distances = new float[state.quadCenters().length];
int[] indexes = new int[state.quadCenters().length];

for (int i = 0; i < state.quadCenters().length; i++) {
distances[i] = state.quadCenters()[i].distanceSquared(point);
indexes[i] = i;
}
IntArrays.mergeSort(indexes, (a,b) -> Float.compare(distances[a], distances[b]));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Checkstyle] <com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAfterCheck> reported by reviewdog 🐶
',' is not followed by whitespace.

return indexes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package dev.dubhe.anvilcraft.api.rendering.foundation.buffer;

public interface BufferHost {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.dubhe.anvilcraft.api.rendering.foundation.buffer;

import dev.dubhe.anvilcraft.api.rendering.foundation.Disposable;
import org.lwjgl.opengl.GL;

import static org.lwjgl.opengl.GL45.*;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Checkstyle] <com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck> reported by reviewdog 🐶
Using the '.' form of import should be avoided - org.lwjgl.opengl.GL45..


public abstract class GlBufferStorage<C> implements Disposable {
public static final boolean BUFFER_STORAGE_SUPPORT = GL.getCapabilities().GL_ARB_buffer_storage && System.getProperty("anvilcraft.enforceLegacyBuffers") == null;
protected final int glBufferId;
protected final int target;
protected boolean valid = true;

static {
if (BUFFER_STORAGE_SUPPORT) {
System.out.println("Using GL_ARB_buffer_storage as buffer storage.");
}
}

GlBufferStorage(int target, C configureContext) {
this.target = target;
this.glBufferId = glGenBuffers();
}

public abstract void setupBufferState(C configureContext);

public void upload(long ptr, long size, Disposable uploadSrc) {
this.upload(ptr, size);
uploadSrc.dispose();
}

/**
* Runs on worker thread
*/
public abstract void upload(long ptr, long size);

public void bind() {
glBindBuffer(target, glBufferId);
}

@Override
public void dispose() {
if (!valid) return;
bind();
glDeleteBuffers(glBufferId);
unbind();
valid = false;
}

public void unbind() {
glBindBuffer(target, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.dubhe.anvilcraft.api.rendering.foundation.buffer;

import com.mojang.blaze3d.systems.RenderSystem;
import dev.dubhe.anvilcraft.api.rendering.foundation.Disposable;

import static org.lwjgl.opengl.GL45.*;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Checkstyle] <com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck> reported by reviewdog 🐶
Using the '.' form of import should be avoided - org.lwjgl.opengl.GL45..


public abstract class GlBufferStorageLegacy<C> extends GlBufferStorage<C> {

protected GlBufferStorageLegacy(int target,C configureContext) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [Checkstyle] <com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAfterCheck> reported by reviewdog 🐶
',' is not followed by whitespace.

super(target, configureContext);
bind();
this.setupBufferState(configureContext);
}

@Override
public void upload(long ptr, long size, Disposable disposable) {
if (RenderSystem.isOnRenderThread()) {
nglBufferData(this.target, size, ptr, GL_STATIC_DRAW);
disposable.dispose();
return;
}
RenderSystem.recordRenderCall(() -> {
nglBufferData(this.target, size, ptr, GL_STATIC_DRAW);
disposable.dispose();
}
);
}

public void upload(long ptr, long size) {
if (RenderSystem.isOnRenderThread()) {
nglBufferData(this.target, size, ptr, GL_STATIC_DRAW);
return;
}
RenderSystem.recordRenderCall(() -> {
nglBufferData(this.target, size, ptr, GL_STATIC_DRAW);
}
);
}
}
Loading
Loading