This commit is contained in:
mcrcortex
2025-04-25 00:27:54 +10:00
parent f7e8ceaa3f
commit 03e79db0ba
12 changed files with 107 additions and 26 deletions

View File

@@ -3,10 +3,10 @@ package me.cortex.voxy.client;
import me.cortex.voxy.common.world.WorldEngine;
public class RenderStatistics {
public static boolean enabled = true;
public static boolean enabled = false;
public static final int[] hierarchicalTraversalCounts = new int[WorldEngine.MAX_LOD_LAYER+1];
public static final int[] hierarchicalRenderSections = new int[WorldEngine.MAX_LOD_LAYER+1];
public static final int[] visibleSections = new int[WorldEngine.MAX_LOD_LAYER+1];
public static int renderedQuadCount = 0;
public static final int[] quadCount = new int[WorldEngine.MAX_LOD_LAYER+1];
}

View File

@@ -29,6 +29,7 @@ public class VoxyConfig implements OptionStorage<VoxyConfig> {
public int serviceThreads = Math.max(Runtime.getRuntime().availableProcessors()/2, 1);
public float subDivisionSize = 128;
public boolean renderVanillaFog = false;
public boolean renderStatistics = false;
public static VoxyConfig loadOrCreate() {
var path = getConfigPath();

View File

@@ -3,16 +3,14 @@ package me.cortex.voxy.client.config;
import com.google.common.collect.ImmutableList;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import me.cortex.voxy.client.RenderStatistics;
import me.cortex.voxy.client.VoxyClientInstance;
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import me.cortex.voxy.commonImpl.VoxyCommon;
import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI;
import net.caffeinemc.mods.sodium.client.gui.options.OptionGroup;
import net.caffeinemc.mods.sodium.client.gui.options.OptionImpact;
import net.caffeinemc.mods.sodium.client.gui.options.OptionImpl;
import net.caffeinemc.mods.sodium.client.gui.options.OptionPage;
import net.caffeinemc.mods.sodium.client.gui.options.*;
import net.caffeinemc.mods.sodium.client.gui.options.control.SliderControl;
import net.caffeinemc.mods.sodium.client.gui.options.control.TickBoxControl;
import net.minecraft.client.MinecraftClient;
@@ -147,6 +145,13 @@ public abstract class VoxyConfigScreenPages {
.setControl(TickBoxControl::new)
.setBinding((s, v)-> s.renderVanillaFog = v, s -> s.renderVanillaFog)
.build()
).add(OptionImpl.createBuilder(boolean.class, storage)
.setName(Text.translatable("voxy.config.general.render_statistics"))
.setTooltip(Text.translatable("voxy.config.general.render_statistics.tooltip"))
.setControl(TickBoxControl::new)
.setBinding((s, v)-> RenderStatistics.enabled = v, s -> RenderStatistics.enabled)
.setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD)
.build()
).build()
);
return new OptionPage(Text.translatable("voxy.config.title"), ImmutableList.copyOf(groups));

View File

@@ -115,7 +115,7 @@ public class ModelTextureBakery {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glDepthRange(0, 1);
//glDepthRange(0, 1);
glDepthMask(true);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);

View File

@@ -36,6 +36,12 @@ public class RenderDistanceTracker {
}
public void setCenterAndProcess(double x, double z) {
//Do some very cheeky stuff for MiB
if (false) {
int sector = (((int)Math.floor(x)>>4)+512)>>10;
x -= sector<<14;//10+4
}
double dx = this.posX-x;
double dz = this.posZ-z;
if (CHECK_DISTANCE_BLOCKS*CHECK_DISTANCE_BLOCKS<dx*dx+dz*dz) {

View File

@@ -54,9 +54,11 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
this.world = world;
this.modelService = new ModelBakerySubsystem(world.getMapper());
//Max sections: ~500k
//Max geometry: 1 gb
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, Math.min((1L<<(64-Long.numberOfLeadingZeros(Capabilities.INSTANCE.ssboMaxSize-1)))<<1, 1L<<32)-1024/*(1L<<32)-1024*/);
long geometryCapacity = Math.min((1L<<(64-Long.numberOfLeadingZeros(Capabilities.INSTANCE.ssboMaxSize-1)))<<1, 1L<<32)-1024/*(1L<<32)-1024*/;
// geometryCapacity = 1<<24;
//Max sections: ~500k
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, geometryCapacity);
Logger.info("Using renderer: " + this.sectionRenderer.getClass().getSimpleName());
//Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard
@@ -163,6 +165,8 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
if (RenderStatistics.enabled) {
debug.add("HTC: [" + Arrays.stream(flipCopy(RenderStatistics.hierarchicalTraversalCounts)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
debug.add("HRS: [" + Arrays.stream(flipCopy(RenderStatistics.hierarchicalRenderSections)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
debug.add("VS: [" + Arrays.stream(flipCopy(RenderStatistics.visibleSections)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
debug.add("QC: [" + Arrays.stream(flipCopy(RenderStatistics.quadCount)).mapToObj(Integer::toString).collect(Collectors.joining(", "))+"]");
}
}

View File

@@ -1,6 +1,7 @@
package me.cortex.voxy.client.core.rendering.section;
import me.cortex.voxy.client.RenderStatistics;
import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType;
@@ -8,6 +9,7 @@ import me.cortex.voxy.client.core.model.ModelStore;
import me.cortex.voxy.client.core.rendering.LightMapHelper;
import me.cortex.voxy.client.core.rendering.RenderService;
import me.cortex.voxy.client.core.rendering.SharedIndexBuffer;
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.rendering.util.UploadStream;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.math.MathHelper;
@@ -34,6 +36,7 @@ import static org.lwjgl.opengl.GL45.glCopyNamedBufferSubData;
//Uses MDIC to render the sections
public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, BasicSectionGeometryManager> {
private static final int TRANSLUCENT_OFFSET = 400_000;//in draw calls
private static final int STATISTICS_BUFFER_BINDING = 7;
private final Shader terrainShader = Shader.make()
.defineIf("DEBUG_RENDER", false)
.add(ShaderType.VERTEX, "voxy:lod/gl46/quads2.vert")
@@ -42,6 +45,10 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
private final Shader commandGenShader = Shader.make()
.define("TRANSLUCENT_OFFSET", TRANSLUCENT_OFFSET)
.defineIf("HAS_STATISTICS", RenderStatistics.enabled)
.defineIf("STATISTICS_BUFFER_BINDING", RenderStatistics.enabled, STATISTICS_BUFFER_BINDING)
.add(ShaderType.COMPUTE, "voxy:lod/gl46/cmdgen.comp")
.compile();
@@ -61,6 +68,9 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
private final GlBuffer drawCallBuffer = new GlBuffer(5*4*(400_000+100_000)).zero();//400k draw calls
private final GlBuffer positionScratchBuffer = new GlBuffer(8*400000).zero();//400k positions
//Statistics
private final GlBuffer statisticsBuffer = new GlBuffer(1024).zero();
public MDICSectionRenderer(ModelStore modelStore, int maxSectionCount, long geometryCapacity) {
super(modelStore, new BasicSectionGeometryManager(maxSectionCount, geometryCapacity));
}
@@ -184,9 +194,26 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, viewport.visibilityBuffer.id);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, viewport.indirectLookupBuffer.id);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.positionScratchBuffer.id);
if (RenderStatistics.enabled) {
this.statisticsBuffer.zero();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, STATISTICS_BUFFER_BINDING, this.statisticsBuffer.id);
}
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, this.drawCountCallBuffer.id);
glDispatchComputeIndirect(0);
glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
glMemoryBarrier(GL_COMMAND_BARRIER_BIT|GL_SHADER_STORAGE_BARRIER_BIT);
if (RenderStatistics.enabled) {
DownloadStream.INSTANCE.download(this.statisticsBuffer, down->{
for (int i = 0; i < 5; i++) {
RenderStatistics.visibleSections[i] = MemoryUtil.memGetInt(down.address+i*4L);
}
for (int i = 0; i < 5; i++) {
RenderStatistics.quadCount[i] = MemoryUtil.memGetInt(down.address+5*4L+i*4L);
}
});
}
}
}
@@ -237,5 +264,6 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
this.drawCallBuffer.free();
this.drawCountCallBuffer.free();
this.positionScratchBuffer.free();
this.statisticsBuffer.free();
}
}

View File

@@ -14,6 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class MixinWindow {
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/Window;throwOnGlError()V"))
private void injectInitWindow(WindowEventHandler eventHandler, MonitorTracker monitorTracker, WindowSettings settings, String fullscreenVideoMode, String title, CallbackInfo ci) {
//System.load("C:\\Program Files\\RenderDoc\\renderdoc.dll");
var prop = System.getProperty("voxy.forceGpuSelectionIndex", "NO");
if (!prop.equals("NO")) {
GPUSelectorWindows2.doSelector(Integer.parseInt(prop));

View File

@@ -388,7 +388,7 @@ public class DHImporter implements IDataImporter {
hasJDBC = true;
} catch (ClassNotFoundException | NoClassDefFoundError e) {
//throw new RuntimeException(e);
Logger.error("Unable to load sqlite JDBC or lzma decompressor, DHImporting wont be available", e);
Logger.warn("Unable to load sqlite JDBC or lzma decompressor, DHImporting wont be available", e);
}
HasRequiredLibraries = hasJDBC;
}

View File

@@ -20,5 +20,8 @@
"voxy.config.general.renderDistance.tooltip": "Render distance of voxy in chunks",
"voxy.config.general.vanilla_fog": "Enable vanilla fog",
"voxy.config.general.vanilla_fog.tooltip": "Enables or disables vanilla fog effect"
"voxy.config.general.vanilla_fog.tooltip": "Enables or disables vanilla fog effect",
"voxy.config.general.render_statistics": "Enable render statistics",
"voxy.config.general.render_statistics.tooltip": "Enable render statistics in F3 menu, useful for debugging"
}

View File

@@ -20,6 +20,12 @@ layout(local_size_x = 128) in;
// adds support for uint8_t which can use for compact visibility buffer
#ifdef HAS_STATISTICS
layout(binding = STATISTICS_BUFFER_BINDING, std430) restrict buffer statisticsBuffer {
uint visibleSectionCounts[5];
uint quadCounts[5];
};
#endif
/*
uint count;
@@ -29,11 +35,6 @@ layout(local_size_x = 128) in;
uint baseInstance;
*/
uint encodeLocalLodPos(uint detail, ivec3 pos) {
uvec3 detla = (pos - (baseSectionPos >> detail))&((1<<9)-1);
return (detail<<27)|(detla.x<<18)|(detla.y<<9)|(detla.z);
}
//Note: if i want reverse indexing i need to use the index buffer offset to offset
void writeCmd(uint idx, uint instance, uint offset, uint quadCount) {
@@ -69,12 +70,13 @@ void main() {
//TODO: need to make it check that only if it was also in the frustum last frame does it apply the visibilityData check!
// this fixes temporal coherance
//This prevents overflow of the relative position encoder
if (shouldRender) {
}
if (shouldRender) {
#ifdef HAS_STATISTICS
atomicAdd(visibleSectionCounts[detail], 1);
#endif
uint ptr = extractQuadStart(meta);
ivec3 relative = ipos-(baseSectionPos>>detail);
uint drawId = gl_GlobalInvocationID.x;
@@ -95,6 +97,9 @@ void main() {
uint cmdPtr = atomicAdd(opaqueDrawCount, bitCount(msk));
#ifdef HAS_STATISTICS
uint totalQuads = 0;
#endif
uint count = 0;
//Translucency
@@ -102,6 +107,9 @@ void main() {
if (count != 0) {
uint translucentCommandPtr = atomicAdd(translucentDrawCount, 1) + TRANSLUCENT_OFFSET;//FIXME: dont hardcode this offset
writeCmd(translucentCommandPtr, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -109,6 +117,9 @@ void main() {
count = (meta.cntA>>16)&0xFFFF;
if (count != 0) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -116,6 +127,9 @@ void main() {
count = (meta.cntB)&0xFFFF;
if (((msk&(1u<<0))!=0)) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -123,6 +137,9 @@ void main() {
count = (meta.cntB>>16)&0xFFFF;
if ((msk&(1u<<1))!=0) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -130,6 +147,9 @@ void main() {
count = (meta.cntC)&0xFFFF;
if ((msk&(1u<<2))!=0) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -137,6 +157,9 @@ void main() {
count = (meta.cntC>>16)&0xFFFF;
if ((msk&(1u<<3))!=0) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -144,6 +167,9 @@ void main() {
count = (meta.cntD)&0xFFFF;
if ((msk&(1u<<4))!=0) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
@@ -151,7 +177,14 @@ void main() {
count = (meta.cntD>>16)&0xFFFF;
if ((msk&(1u<<5))!=0) {
writeCmd(cmdPtr++, drawId, ptr, count);
#ifdef HAS_STATISTICS
totalQuads += count;
#endif
}
ptr += count;
#ifdef HAS_STATISTICS
atomicAdd(quadCounts[detail], totalQuads);
#endif
}
}

View File

@@ -37,12 +37,12 @@ bool checkPointInView(vec4 point) {
return within(vec3(-point.w,-point.w,0.0f), point.xyz, vec3(point.w));
}
vec3 minBB;
vec3 maxBB;
vec2 size;
bool insideFrustum;
vec3 minBB = vec3(0.0f);
vec3 maxBB = vec3(0.0f);
vec2 size = vec2(0.0f);
bool insideFrustum = false;
float screenSize;
float screenSize = 0.0f;
UnpackedNode node22;
//Sets up screenspace with the given node id, returns true on success false on failure/should not continue