Skip to content

Commit

Permalink
voxel testing
Browse files Browse the repository at this point in the history
  • Loading branch information
IMS212 committed Dec 21, 2024
1 parent df32670 commit d03fcdb
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ public long getOffset() {
return UInt32.upcast(this.offset);
}

@Override
public String toString() {
return "GlBufferSegment{" +
"offset=" + offset +
", length=" + length +
", free=" + free +
'}';
}

/* Uint32 */
public long getLength() {
return UInt32.upcast(this.length);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net.caffeinemc.mods.sodium.client.render.chunk;

import org.lwjgl.opengl.GL46C;
import org.lwjgl.system.MemoryUtil;

public class PersistentVoxelBuffer {
private final int id;
private final long capacity;
private long mapping;
private boolean flushIfNeeded;
private long minRange = Long.MAX_VALUE, maxRange = Long.MIN_VALUE;

public PersistentVoxelBuffer(long capacity) {
this.id = GL46C.glCreateBuffers();
this.capacity = capacity;

GL46C.glNamedBufferStorage(id, capacity, GL46C.GL_MAP_WRITE_BIT | GL46C.GL_MAP_PERSISTENT_BIT);

mapping = GL46C.nglMapNamedBufferRange(id, 0, capacity, GL46C.GL_MAP_WRITE_BIT | GL46C.GL_MAP_FLUSH_EXPLICIT_BIT | GL46C.GL_MAP_PERSISTENT_BIT);
}

public int getId() {
return id;
}

public void write(long offset, int id) {
flushIfNeeded = true;
minRange = Math.min(minRange, offset);
maxRange = Math.max(maxRange, offset + 4);
MemoryUtil.memPutInt(mapping + offset, id);
}

public void flush() {
if (flushIfNeeded) {
GL46C.glFlushMappedNamedBufferRange(id, minRange, maxRange - minRange);

minRange = Long.MAX_VALUE;
maxRange = Long.MIN_VALUE;
flushIfNeeded = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.caffeinemc.mods.sodium.client.render.chunk;

import net.caffeinemc.mods.sodium.client.gl.arena.GlBufferSegment;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.estimation.MeshResultSize;
import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionInfo;
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.GraphDirection;
Expand All @@ -13,6 +14,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.math.BigInteger;

/**
* The render state object for a chunk section. This contains all the graphics state for each render pass along with
* data about the render in the chunk visibility graph.
Expand Down Expand Up @@ -58,6 +61,8 @@ public class RenderSection {

// Lifetime state
private boolean disposed;
private GlBufferSegment voxelData;
private boolean sentVoxelData;

public RenderSection(RenderRegion region, int chunkX, int chunkY, int chunkZ) {
this.chunkX = chunkX;
Expand Down Expand Up @@ -157,6 +162,11 @@ private boolean clearRenderState() {
var wasBuilt = this.isBuilt();

this.region.clearSectionRenderState(this.sectionIndex);
if (this.voxelData != null) {
this.sentVoxelData = false;
this.voxelData.delete();
this.voxelData = null;
}
this.visibilityData = VisibilityEncoding.NULL;

// changes to data if it moves from built to not built don't matter, so only build state changes matter
Expand Down Expand Up @@ -348,4 +358,34 @@ public int getLastSubmittedFrame() {
public void setLastSubmittedFrame(int lastSubmittedFrame) {
this.lastSubmittedFrame = lastSubmittedFrame;
}

public void setVoxelData(PersistentVoxelBuffer b, int diameter, int chunkYSize, GlBufferSegment result) {
this.voxelData = result;
if (getChunkX() == 627 && getChunkY() == 4 && getChunkZ() == 624) {
System.out.println("Voxel data set for chunk " + getChunkX() + ", " + getChunkY() + ", " + getChunkZ());
System.out.println("Location: " + getVoxelLocation(diameter, chunkYSize));
System.out.println("Voxel Data Offset: " + BigInteger.valueOf(getVoxelData().getOffset()).divide(BigInteger.valueOf(32768)));
System.out.println(getVoxelData());
}
b.write(getVoxelLocation(diameter, chunkYSize) * 4L, (int) (getVoxelData().getOffset() / 32768L));
}

private int getVoxelLocation(int renderDiameter, int chunkZAmount) {
int x = getChunkX() % renderDiameter;
int y = getChunkY() % chunkZAmount;
int z = getChunkZ() % renderDiameter;
return x + y * renderDiameter + z * renderDiameter * chunkZAmount;
}

public GlBufferSegment getVoxelData() {
return voxelData;
}

public boolean sentVoxelData() {
return sentVoxelData;
}

public void markSentVoxelData() {
this.sentVoxelData = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import it.unimi.dsi.fastutil.longs.*;
import it.unimi.dsi.fastutil.objects.*;
import net.caffeinemc.mods.sodium.client.SodiumClientMod;
import net.caffeinemc.mods.sodium.client.gl.arena.GlBufferArena;
import net.caffeinemc.mods.sodium.client.gl.device.CommandList;
import net.caffeinemc.mods.sodium.client.gl.device.RenderDevice;
import net.caffeinemc.mods.sodium.client.render.chunk.async.*;
Expand Down Expand Up @@ -52,6 +53,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3dc;
import org.lwjgl.opengl.GL46C;

import java.util.*;
import java.util.concurrent.ConcurrentLinkedDeque;
Expand Down Expand Up @@ -118,6 +120,7 @@ public class RenderSectionManager {
private final Map<CullType, SectionTree> trees = new EnumMap<>(CullType.class);

private final AsyncCameraTimingControl cameraTimingControl = new AsyncCameraTimingControl();
private final PersistentVoxelBuffer persistentBuffer;

public RenderSectionManager(ClientLevel level, int renderDistance, CommandList commandList) {
this.chunkRenderer = new DefaultChunkRenderer(RenderDevice.INSTANCE, ChunkMeshFormats.COMPACT);
Expand All @@ -129,7 +132,11 @@ public RenderSectionManager(ClientLevel level, int renderDistance, CommandList c

this.sortTriggering = new SortTriggering();

this.regions = new RenderRegionManager(commandList);
this.regions = new RenderRegionManager(this, commandList, level, renderDistance);
int diameter = (renderDistance * 2) + 1;

this.persistentBuffer = new PersistentVoxelBuffer(diameter * diameter * Math.abs(level.getMinSectionY() - level.getMaxSectionY()) * 4L);

this.sectionCache = new ClonedChunkSectionCache(this.level);

this.renderLists = SortedRenderLists.empty();
Expand Down Expand Up @@ -211,11 +218,14 @@ private void renderSync(Camera camera, Viewport viewport, boolean spectator) {
task.getResult();
}
this.pendingTasks.clear();
int diameter = (renderDistance * 2) + 1;

var tree = new VisibleChunkCollectorSync(viewport, searchDistance, this.frame, CullType.FRUSTUM, this.level);
var tree = new VisibleChunkCollectorSync(viewport, searchDistance, this.frame, CullType.FRUSTUM, this.level, this.persistentBuffer, diameter, Math.abs(level.getMinSectionY() - level.getMaxSectionY()));
this.occlusionCuller.findVisible(tree, viewport, searchDistance, useOcclusionCulling, CancellationToken.NEVER_CANCELLED);
tree.finalizeTrees();

this.persistentBuffer.flush();

this.frustumTaskLists = tree.getPendingTaskLists();
this.globalTaskLists = null;
this.trees.put(CullType.FRUSTUM, tree);
Expand Down Expand Up @@ -516,6 +526,9 @@ public void renderLayer(ChunkRenderMatrices matrices, TerrainRenderPass pass, do
RenderDevice device = RenderDevice.INSTANCE;
CommandList commandList = device.createCommandList();

GL46C.glBindBufferBase(GL46C.GL_SHADER_STORAGE_BUFFER, 3, this.persistentBuffer.getId());
GL46C.glBindBufferBase(GL46C.GL_SHADER_STORAGE_BUFFER, 4, this.regions.voxelArena.getBufferObject().handle());

this.chunkRenderer.render(matrices, commandList, this.renderLists, pass, new CameraTransform(x, y, z));

commandList.flush();
Expand Down Expand Up @@ -823,7 +836,7 @@ private long submitSectionTasks(long remainingUploadSize, boolean limitOnSize, C
// index data.
var result = ChunkJobResult.successfully(new ChunkBuildOutput(
section, this.frame, NoData.forEmptySection(section.getPosition()),
BuiltSectionInfo.EMPTY, Collections.emptyMap()));
BuiltSectionInfo.EMPTY, Collections.emptyMap(), null));
this.buildResults.add(result);

section.setTaskCancellationToken(null);
Expand Down Expand Up @@ -1121,4 +1134,8 @@ public void onChunkRemoved(int x, int z) {
public Collection<RenderSection> getSectionsWithGlobalEntities() {
return ReferenceSets.unmodifiable(this.sectionsWithGlobalEntities);
}

public PersistentVoxelBuffer getPersistentBuffer() {
return persistentBuffer;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package net.caffeinemc.mods.sodium.client.render.chunk.compile;

import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.VoxelBuffer;
import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionInfo;
import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionMeshParts;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass;
import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.data.TranslucentData;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

Expand All @@ -18,14 +20,16 @@ public class ChunkBuildOutput extends ChunkSortOutput {
public final BuiltSectionInfo info;
public final TranslucentData translucentData;
public final Map<TerrainRenderPass, BuiltSectionMeshParts> meshes;
private final VoxelBuffer voxels;

public ChunkBuildOutput(RenderSection render, int buildTime, TranslucentData translucentData, BuiltSectionInfo info,
Map<TerrainRenderPass, BuiltSectionMeshParts> meshes) {
Map<TerrainRenderPass, BuiltSectionMeshParts> meshes, VoxelBuffer voxels) {
super(render, buildTime);

this.info = info;
this.translucentData = translucentData;
this.meshes = meshes;
this.voxels = voxels;
}

public BuiltSectionMeshParts getMesh(TerrainRenderPass pass) {
Expand All @@ -39,6 +43,10 @@ public void destroy() {
for (BuiltSectionMeshParts data : this.meshes.values()) {
data.getVertexData().free();
}

if (voxels != null) {
voxels.delete();
}
}

private long getMeshSize() {
Expand All @@ -49,6 +57,11 @@ private long getMeshSize() {
return size;
}

@Nullable
public VoxelBuffer getVoxels() {
return voxels;
}

@Override
public long calculateResultSize() {
return super.calculateResultSize() + this.getMeshSize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.chunk.VisGraph;
import net.minecraft.client.resources.model.BakedModel;
Expand Down Expand Up @@ -66,6 +67,8 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke
ChunkBuildBuffers buffers = buildContext.buffers;
buffers.init(renderData, this.render.getSectionIndex());

VoxelBuffer voxels = new VoxelBuffer();

BlockRenderCache cache = buildContext.cache;
cache.init(this.renderContext);

Expand Down Expand Up @@ -104,12 +107,16 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke
BlockState blockState = slice.getBlockState(x, y, z);

if (blockState.isAir() && !blockState.hasBlockEntity()) {
voxels.write(x & 15, y & 15, z & 15, 0, 0);
continue;
}

blockPos.set(x, y, z);
modelOffset.set(x & 15, y & 15, z & 15);

// todo perf
voxels.write(x & 15, y & 15, z & 15, 99, LevelRenderer.getLightColor(slice, blockState, blockPos));

if (blockState.getRenderShape() == RenderShape.MODEL) {
BakedModel model = cache.getBlockModels()
.getBlockModel(blockState);
Expand Down Expand Up @@ -176,6 +183,7 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke
// cancellation opportunity right before translucent sorting
if (cancellationToken.isCancelled()) {
meshes.forEach((pass, mesh) -> mesh.getVertexData().free());
voxels.delete();
profiler.pop();
return null;
}
Expand All @@ -193,7 +201,7 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke
reuseUploadedData = translucentData == oldData;
}

var output = new ChunkBuildOutput(this.render, this.submitTime, translucentData, renderData.build(), meshes);
var output = new ChunkBuildOutput(this.render, this.submitTime, translucentData, renderData.build(), meshes, voxels);

if (collector != null) {
if (reuseUploadedData) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks;

import net.caffeinemc.mods.sodium.client.util.NativeBuffer;
import org.lwjgl.system.MemoryUtil;

public class VoxelBuffer {
private final NativeBuffer buffer;

public static final int VOXEL_SIZE = 8;

public VoxelBuffer() {
buffer = new NativeBuffer((16 * 16 * 16) * VOXEL_SIZE);
}

public void write(int x, int y, int z, int id, int light) {
long index = this.buffer.getPointer() + (x + y * 16L + z * 16L * 16L);
MemoryUtil.memPutInt(index, id);
MemoryUtil.memPutInt(index + 4, light);
}

public NativeBuffer getBuffer() {
return buffer;
}

public void delete() {
buffer.free();
}
}
Loading

0 comments on commit d03fcdb

Please sign in to comment.