Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 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, 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