Skip to content

Commit

Permalink
Began work on download system and visibility tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
MCRcortex committed Apr 17, 2023
1 parent 667d026 commit e7d32d0
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 15 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ yarn_mappings=1.19.4+build.1
loader_version=0.14.19
fabric_version=0.76.0+1.19.4
# Mod Properties
mod_version=0.1.2-alpha
mod_version=0.1.3-alpha
maven_group=me.cortex
archives_base_name=nvidium
# Dependencies
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/me/cortex/nvidium/RenderPipeline.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
import me.cortex.nvidium.gl.RenderDevice;
import me.cortex.nvidium.gl.buffers.IDeviceMappedBuffer;
import me.cortex.nvidium.managers.SectionManager;
import me.cortex.nvidium.managers.VisibilityTracker;
import me.cortex.nvidium.renderers.PrimaryTerrainRasterizer;
import me.cortex.nvidium.renderers.RegionRasterizer;
import me.cortex.nvidium.renderers.SectionRasterizer;
import me.cortex.nvidium.renderers.TranslucentTerrainRasterizer;
import me.cortex.nvidium.util.DownloadTaskStream;
import me.cortex.nvidium.util.TickableManager;
import me.cortex.nvidium.util.UploadingBufferStream;
import me.jellysquid.mods.sodium.client.SodiumClientMod;
import me.jellysquid.mods.sodium.client.render.chunk.ChunkCameraContext;
import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices;
Expand Down Expand Up @@ -57,6 +59,7 @@ public class RenderPipeline {
private static final RenderDevice device = new RenderDevice();

public final SectionManager sectionManager;
public final VisibilityTracker visibilityTracker;

private final PrimaryTerrainRasterizer terrainRasterizer;
private final RegionRasterizer regionRasterizer;
Expand All @@ -70,12 +73,17 @@ public class RenderPipeline {
private final IDeviceMappedBuffer sectionVisibility;
private final IDeviceMappedBuffer terrainCommandBuffer;

private final UploadingBufferStream uploadStream;
private final DownloadTaskStream downloadStream;

private final int bufferSizesMB;

public RenderPipeline() {
sectionManager = new SectionManager(device, MinecraftClient.getInstance().options.getClampedViewDistance(), 24, SodiumClientMod.options().advanced.cpuRenderAheadLimit+1, CompactChunkVertex.STRIDE);
int frames = SodiumClientMod.options().advanced.cpuRenderAheadLimit+1;
this.uploadStream = new UploadingBufferStream(device, frames, 160000000);
this.downloadStream = new DownloadTaskStream(device, frames, 16000000);
sectionManager = new SectionManager(device, uploadStream, MinecraftClient.getInstance().options.getClampedViewDistance(), 24, CompactChunkVertex.STRIDE);
visibilityTracker = new VisibilityTracker(downloadStream, frames, sectionManager.getRegionManager());
terrainRasterizer = new PrimaryTerrainRasterizer();
regionRasterizer = new RegionRasterizer();
sectionRasterizer = new SectionRasterizer();
Expand All @@ -90,7 +98,6 @@ public RenderPipeline() {
cbs += maxRegions * 256L * 2;
terrainCommandBuffer = device.createDeviceOnlyMappedBuffer(maxRegions*8L*7);
cbs += maxRegions*8L*7;
downloadStream = new DownloadTaskStream(device, SodiumClientMod.options().advanced.cpuRenderAheadLimit+1, 16000000);

bufferSizesMB = cbs/(1024*1024);
}
Expand All @@ -111,6 +118,8 @@ public void renderFrame(Frustum frustum, ChunkRenderMatrices crm, ChunkCameraCon
int visibleRegions = 0;
int playerRegion = -1;
int playerRegionId = -1;

short[] vregions;
//Enqueue all the visible regions
{
var rm = sectionManager.getRegionManager();
Expand All @@ -130,11 +139,13 @@ public void renderFrame(Frustum frustum, ChunkRenderMatrices crm, ChunkCameraCon
if (visibleRegions == 0) return;
long addr = sectionManager.uploadStream.getUpload(sceneUniform, SCENE_SIZE, visibleRegions*2);
int j = 0;
vregions = new short[regions.size()];
for (int i : regions) {
if (((short)i) == playerRegionId) {
playerRegion = j;
}
MemoryUtil.memPutShort(addr+((long) j <<1), (short) i);
vregions[j] = ((short)i);
j++;
}
}
Expand Down Expand Up @@ -215,6 +226,9 @@ public void renderFrame(Frustum frustum, ChunkRenderMatrices crm, ChunkCameraCon
}
}

{//Tick the visibility tracker
visibilityTracker.onFrame(vregions, regionVisibility);
}
/*
{//Download the region visibility from the gpu, used for determining culling
downloadStream.download(regionVisibility, 0, visibleRegions, addr->{
Expand Down Expand Up @@ -287,6 +301,8 @@ public void renderTranslucent() {

public void delete() {
sectionManager.delete();
visibilityTracker.delete();

sceneUniform.delete();
regionVisibility.delete();
sectionVisibility.delete();
Expand All @@ -296,6 +312,9 @@ public void delete() {
regionRasterizer.delete();
sectionRasterizer.delete();
translucencyTerrainRasterizer.delete();

downloadStream.delete();
uploadStream.delete();
}

public int getOtherBufferSizesMB() {
Expand Down
41 changes: 40 additions & 1 deletion src/main/java/me/cortex/nvidium/managers/RegionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import me.cortex.nvidium.util.UploadingBufferStream;
import me.jellysquid.mods.sodium.client.util.frustum.Frustum;
import net.minecraft.util.math.ChunkSectionPos;
import org.joml.Vector3i;
import org.lwjgl.system.MemoryUtil;

import java.util.BitSet;
Expand Down Expand Up @@ -45,6 +44,27 @@ public boolean regionIsAtPos(int regionId, int x, int y, int z) {
return region.rx == x && region.ry == y && region.rz == z;
}

public void markVisible(short regionId, int frame) {
var region = regions[regionId];
//Rare case since this is called N frames behind, the region might not exist
// or worse be a completely different region
if (region == null) {
return;
}
region.lastSeenVisible = frame;
region.lastSeenFrustum = frame;
}

public void markFrustum(short regionId, int frame) {
var region = regions[regionId];
//Rare case since this is called N frames behind, the region might not exist
// or worse be a completely different region
if (region == null) {
return;
}
region.lastSeenFrustum = frame;
}

//IDEA: make it so that sections are packed into regions, that is the local index of a chunk is hard coded to its position, and just 256 sections are processed when a region is visible, this has some overhead but means that the exact amount being processed each time is known and the same
private static final class Region {
private final int rx;
Expand Down Expand Up @@ -104,6 +124,10 @@ public long getPackedData() {
(ry<<2)+minY,
(rz<<3)+minZ);
}

public int getVisibilityDelta() {
return lastSeenFrustum - lastSeenVisible;
}
}

public static long getRegionKey(int sectionX, int sectionY, int sectionZ) {
Expand Down Expand Up @@ -164,6 +188,7 @@ public void removeSectionIndex(UploadingBufferStream uploadStream, int sectionId
}
}

//TODO: need to batch changes, cause in alot of cases the region is updated multiple times a frame
private void updateRegion(UploadingBufferStream uploadingStream, Region region) {
long segment = uploadingStream.getUpload(regionBuffer, (long) region.id * META_SIZE, META_SIZE);
MemoryUtil.memPutLong(segment, region.getPackedData());
Expand Down Expand Up @@ -205,4 +230,18 @@ public int distance(int regionId, int camChunkX, int camChunkY, int camChunkZ) {
Math.abs((region.ry<<2)+2-camChunkY)+
Math.abs((region.rz<<3)+4-camChunkZ);
}

public int findMaxSeenDelta() {
int delta = Integer.MIN_VALUE;
int id = -1;
for (int i = 0; i < maxRegionIndex(); i++) {
var region = regions[i];
if (region == null) continue;
if (delta < region.getVisibilityDelta()) {
id = region.id;
delta = region.getVisibilityDelta();
}
}
return id;
}
}
9 changes: 3 additions & 6 deletions src/main/java/me/cortex/nvidium/managers/SectionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@ public class SectionManager {
private final int formatSize;

private final int bufferSize;
public SectionManager(RenderDevice device, int rd, int height, int frames, int quadVertexSize) {
public SectionManager(RenderDevice device, UploadingBufferStream uploadStream, int rd, int height, int quadVertexSize) {
this.device = device;

int bs = 0;
this.uploadStream = new UploadingBufferStream(device, frames, 160000000);
bs += 160000000;
this.uploadStream = uploadStream;
int bs = 16000000;
//int widthSquared = (rd*2+1)*(rd*2+1);

//int maxRegions = (int) Math.ceil((((double) widthSquared*height)/256))*2;
Expand Down Expand Up @@ -130,7 +128,6 @@ public void commitChanges() {
}

public void delete() {
uploadStream.delete();
sectionBuffer.delete();
terrainAreana.delete();
regionManager.delete();
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/me/cortex/nvidium/managers/VisibilityTracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package me.cortex.nvidium.managers;

import me.cortex.nvidium.gl.buffers.Buffer;
import me.cortex.nvidium.util.DownloadTaskStream;
import org.lwjgl.system.MemoryUtil;

//NOTE: the visibility tracker and RenderPipeline must be kept in frame perfect sync else all hell breaks loose
public class VisibilityTracker {
private final DownloadTaskStream downloadStream;
private int frameId;
private final short[][] regions;
private final byte[] frameIds;
private final RegionManager regionManager;
public VisibilityTracker(DownloadTaskStream downloadStream, int frames, RegionManager regionManager) {
this.downloadStream = downloadStream;
this.regionManager = regionManager;
regions = new short[frames][];
frameIds = new byte[frames];
}

public void onFrame(short[] visibleRegions, Buffer regionVisibility) {
frameIds[(frameId)% regions.length] = (byte) (frameId-1);
regions[(frameId++)% regions.length] = visibleRegions;
downloadStream.download(regionVisibility, 0, visibleRegions.length, this::onDownload);
}

private void onDownload(long ptr) {
int pframe = frameId - (this.regions.length - 1);
var regions = this.regions[pframe%this.regions.length];
byte frame = frameIds[pframe%this.regions.length];
for (int i = 0; i < regions.length; i++) {
if (MemoryUtil.memGetByte(ptr + i) == frame) {
regionManager.markVisible(regions[i], pframe);
} else {
regionManager.markFrustum(regions[i], pframe);
}
}
}

public void delete() {

}
}
4 changes: 2 additions & 2 deletions src/main/resources/assets/cortex/shaders/terrain/frag.frag
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
layout(location = 0) out vec4 colour;
layout(location = 1) in Interpolants {
vec4 tint;
vec2 uv;
vec3 uv_bias;
};

layout(binding = 0) uniform sampler2D tex_diffuse;
Expand All @@ -26,7 +26,7 @@ void main() {
//uint uid = gl_PrimitiveID*132471+123571;
//colour = vec4(float((uid>>0)&7)/7, float((uid>>3)&7)/7, float((uid>>6)&7)/7, 1.0);
//colour = vec4(1.0,1.0,0,1);
colour = texture(tex_diffuse, uv);
colour = texture(tex_diffuse, uv_bias.xy, uv_bias.z);
if (colour.a < 0.05f) discard;
colour.xyz *= tint.xyz;
colour.xyz *= tint.w;
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/assets/cortex/shaders/terrain/mesh.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ taskNV in Task {

layout(location=1) out Interpolants {
vec4 tint;
vec2 uv;
vec3 uv_bias;
} OUT[];


Expand Down Expand Up @@ -60,8 +60,9 @@ void main() {
gl_PrimitiveIndicesNV[primId+1] = (isA?1:3)+idxBase;
gl_PrimitiveIndicesNV[primId+2] = (isA?2:0)+idxBase;

OUT[(gl_LocalInvocationID.x<<1)|0].uv = vec2(A.g,A.h)/65535;
OUT[(gl_LocalInvocationID.x<<1)|1].uv = vec2(B.g,B.h)/65535;
uint material = uint(A.d>>8)&0xff;
OUT[(gl_LocalInvocationID.x<<1)|0].uv_bias = vec3(vec2(A.g,A.h)/65535, 0.0f);//(material&1u)!=0u?0.0f:-900.0f);//Temporary untill sodium 0.5
OUT[(gl_LocalInvocationID.x<<1)|1].uv_bias = vec3(vec2(B.g,B.h)/65535, 0.0f);//(material&1u)!=0u?0.0f:-900.0f);//Temporary untill sodium 0.5


vec4 tintA = vec4(A.e&int16_t(0xFF),(A.e>>8)&int16_t(0xFF),A.f&int16_t(0xFF),(A.f>>8)&int16_t(0xFF))/255;
Expand Down

0 comments on commit e7d32d0

Please sign in to comment.