Add support for FREX flawless frames, failed attempt to fix intel igpus

This commit is contained in:
mcrcortex
2025-05-22 19:50:25 +10:00
parent a314c26b89
commit cdfa15c1f6
8 changed files with 77 additions and 34 deletions

View File

@@ -6,11 +6,17 @@ import me.cortex.voxy.commonImpl.VoxyCommon;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import java.util.HashSet;
import java.util.function.Consumer;
import java.util.function.Function;
public class VoxyClient implements ClientModInitializer { public class VoxyClient implements ClientModInitializer {
private static final HashSet<String> FREX = new HashSet<>();
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
ClientLifecycleEvents.CLIENT_STARTED.register(client->{ ClientLifecycleEvents.CLIENT_STARTED.register(client->{
boolean systemSupported = Capabilities.INSTANCE.compute && Capabilities.INSTANCE.indirectParameters; boolean systemSupported = Capabilities.INSTANCE.compute && Capabilities.INSTANCE.indirectParameters;
if (systemSupported) { if (systemSupported) {
@@ -26,5 +32,17 @@ public class VoxyClient implements ClientModInitializer {
dispatcher.register(VoxyCommands.register()); dispatcher.register(VoxyCommands.register());
} }
}); });
FabricLoader.getInstance()
.getEntrypoints("frex_flawless_frames", Consumer.class)
.forEach(api -> ((Consumer<Function<String,Consumer<Boolean>>>)api).accept(name->active->{if (active) {
FREX.add(name);
} else {
FREX.remove(name);
}}));
}
public static boolean isFrexActive() {
return !FREX.isEmpty();
} }
} }

View File

@@ -4,6 +4,7 @@ import com.mojang.blaze3d.opengl.GlConst;
import com.mojang.blaze3d.opengl.GlStateManager; import com.mojang.blaze3d.opengl.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import me.cortex.voxy.client.TimingStatistics; import me.cortex.voxy.client.TimingStatistics;
import me.cortex.voxy.client.VoxyClient;
import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.client.config.VoxyConfig;
import me.cortex.voxy.client.core.gl.Capabilities; import me.cortex.voxy.client.core.gl.Capabilities;
import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlBuffer;
@@ -233,7 +234,7 @@ public class VoxyRenderSystem {
//Tick upload stream (this is ok to do here as upload ticking is just memory management) //Tick upload stream (this is ok to do here as upload ticking is just memory management)
UploadStream.INSTANCE.tick(); UploadStream.INSTANCE.tick();
this.renderDistanceTracker.setCenterAndProcess(cameraX, cameraZ); while (this.renderDistanceTracker.setCenterAndProcess(cameraX, cameraZ) && VoxyClient.isFrexActive());//While FF is active, run until everything is processed
//Done here as is allows less gl state resetup //Done here as is allows less gl state resetup
this.renderer.tickModelService(Math.max(3_000_000-(System.nanoTime()-startTime), 500_000)); this.renderer.tickModelService(Math.max(3_000_000-(System.nanoTime()-startTime), 500_000));

View File

@@ -22,6 +22,8 @@ public class Capabilities {
public final long totalDynamicMemory;//Bytes, total allocation memory - dedicated memory public final long totalDynamicMemory;//Bytes, total allocation memory - dedicated memory
public final boolean compute; public final boolean compute;
public final boolean indirectParameters; public final boolean indirectParameters;
public final boolean isIntel;
public Capabilities() { public Capabilities() {
var cap = GL.getCapabilities(); var cap = GL.getCapabilities();
this.compute = cap.glDispatchComputeIndirect != 0; this.compute = cap.glDispatchComputeIndirect != 0;
@@ -42,6 +44,7 @@ public class Capabilities {
this.ssboMaxSize = glGetInteger64(GL_MAX_SHADER_STORAGE_BLOCK_SIZE); this.ssboMaxSize = glGetInteger64(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
this.isMesa = glGetString(GL_VERSION).toLowerCase().contains("mesa"); this.isMesa = glGetString(GL_VERSION).toLowerCase().contains("mesa");
this.isIntel = glGetString(GL_VENDOR).toLowerCase().contains("intel");
if (this.canQueryGpuMemory) { if (this.canQueryGpuMemory) {
this.totalDedicatedMemory = glGetInteger64(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX)*1024;//Since its in Kb this.totalDedicatedMemory = glGetInteger64(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX)*1024;//Since its in Kb

View File

@@ -1,5 +1,6 @@
package me.cortex.voxy.client.core.gl.shader; package me.cortex.voxy.client.core.gl.shader;
import me.cortex.voxy.client.core.gl.Capabilities;
import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlDebug; import me.cortex.voxy.client.core.gl.GlDebug;
import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.Logger;
@@ -147,6 +148,7 @@ public class Shader extends TrackedObject {
} }
public T compile() { public T compile() {
this.defineIf("IS_INTEL", Capabilities.INSTANCE.isIntel);
return this.constructor.make(this, this.compileToProgram()); return this.constructor.make(this, this.compileToProgram());
} }

View File

@@ -35,7 +35,7 @@ public class RenderDistanceTracker {
this.tracker = new RingTracker(this.tracker, renderDistance, ((int)this.posX)>>9, ((int)this.posZ)>>9, true);//Steal from previous tracker this.tracker = new RingTracker(this.tracker, renderDistance, ((int)this.posX)>>9, ((int)this.posZ)>>9, true);//Steal from previous tracker
} }
public void setCenterAndProcess(double x, double z) { public boolean setCenterAndProcess(double x, double z) {
double dx = this.posX-x; double dx = this.posX-x;
double dz = this.posZ-z; double dz = this.posZ-z;
if (CHECK_DISTANCE_BLOCKS*CHECK_DISTANCE_BLOCKS<dx*dx+dz*dz) { if (CHECK_DISTANCE_BLOCKS*CHECK_DISTANCE_BLOCKS<dx*dx+dz*dz) {
@@ -43,7 +43,7 @@ public class RenderDistanceTracker {
this.posZ = z; this.posZ = z;
this.tracker.moveCenter(((int)x)>>9, ((int)z)>>9); this.tracker.moveCenter(((int)x)>>9, ((int)z)>>9);
} }
this.tracker.process(this.processRate, this::add, this::rem); return this.tracker.process(this.processRate, this::add, this::rem)!=0;
} }
private void add(int x, int z) { private void add(int x, int z) {

View File

@@ -2,6 +2,7 @@ package me.cortex.voxy.client.core.rendering;
import me.cortex.voxy.client.RenderStatistics; import me.cortex.voxy.client.RenderStatistics;
import me.cortex.voxy.client.TimingStatistics; import me.cortex.voxy.client.TimingStatistics;
import me.cortex.voxy.client.VoxyClient;
import me.cortex.voxy.client.core.gl.Capabilities; import me.cortex.voxy.client.core.gl.Capabilities;
import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.GlTexture;
import me.cortex.voxy.client.core.model.ModelBakerySubsystem; import me.cortex.voxy.client.core.model.ModelBakerySubsystem;
@@ -14,6 +15,7 @@ import me.cortex.voxy.client.core.rendering.section.geometry.*;
import me.cortex.voxy.client.core.rendering.section.IUsesMeshlets; import me.cortex.voxy.client.core.rendering.section.IUsesMeshlets;
import me.cortex.voxy.client.core.rendering.section.MDICSectionRenderer; import me.cortex.voxy.client.core.rendering.section.MDICSectionRenderer;
import me.cortex.voxy.client.core.rendering.util.DownloadStream; import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.rendering.util.UploadStream;
import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.world.WorldEngine; import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.common.thread.ServiceThreadPool; import me.cortex.voxy.common.thread.ServiceThreadPool;
@@ -117,15 +119,9 @@ public class RenderService<T extends AbstractSectionRenderer<J, Q>, J extends Vi
this.sectionRenderer.renderOpaque(viewport, depthBoundTexture); this.sectionRenderer.renderOpaque(viewport, depthBoundTexture);
TimingStatistics.G.stop(); TimingStatistics.G.stop();
do {
//NOTE: need to do the upload and download tick here, after the section renderer renders the world, to ensure "stable" //NOTE: need to do the upload and download tick here, after the section renderer renders the world, to ensure "stable"
// sections // sections
//FIXME: we only want to tick once per full frame, this is due to how the data of sections is updated
// we basicly need the data to stay stable from one frame to the next, till after renderOpaque
// this is because e.g. shadows, cause this pipeline to be invoked multiple times
// which may cause the geometry to become outdated resulting in corruption rendering in renderOpaque
//TODO: Need to find a proper way to fix this (if there even is one)
{ {
TimingStatistics.main.stop(); TimingStatistics.main.stop();
TimingStatistics.dynamic.start(); TimingStatistics.dynamic.start();
@@ -163,10 +159,21 @@ public class RenderService<T extends AbstractSectionRenderer<J, Q>, J extends Vi
if (depthBuffer == 0) { if (depthBuffer == 0) {
depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
} }
TimingStatistics.I.start(); TimingStatistics.I.start();
this.traversal.doTraversal(viewport, depthBuffer); this.traversal.doTraversal(viewport, depthBuffer);
TimingStatistics.I.stop(); TimingStatistics.I.stop();
if (VoxyClient.isFrexActive()) {//If frex is running we must tick everything to ensure correctness
UploadStream.INSTANCE.tick();
//Done here as is allows less gl state resetup
this.tickModelService(100_000_000);
glFinish();
}
} while (VoxyClient.isFrexActive() && (this.nodeManager.hasWork() || this.renderGen.getTaskCount()!=0 || !this.modelService.areQueuesEmpty()));
TimingStatistics.H.start(); TimingStatistics.H.start();
this.sectionRenderer.buildDrawCalls(viewport); this.sectionRenderer.buildDrawCalls(viewport);
TimingStatistics.H.stop(); TimingStatistics.H.stop();

View File

@@ -717,6 +717,10 @@ public class AsyncNodeManager {
debug.add("UC/GC: " + (this.getUsedGeometryCapacity()/(1<<20))+"/"+(this.getGeometryCapacity()/(1<<20))); debug.add("UC/GC: " + (this.getUsedGeometryCapacity()/(1<<20))+"/"+(this.getGeometryCapacity()/(1<<20)));
} }
public boolean hasWork() {
return this.workCounter.get()!=0 && RESULT_HANDLE.get(this) != null;
}
//Results object, which is to be synced between the render thread and worker thread //Results object, which is to be synced between the render thread and worker thread
private static final class SyncResults { private static final class SyncResults {
//Contains //Contains

View File

@@ -43,12 +43,20 @@ void main() {
barrier(); barrier();
#ifdef IS_INTEL
uint val = subgroupExclusiveAdd(warpPrefixSum[gl_SubgroupInvocationID]);
barrier();
if (gl_SubgroupID == 0) {
warpPrefixSum[gl_SubgroupInvocationID] = val;
}
#else
if (gl_SubgroupID == 0) { if (gl_SubgroupID == 0) {
uint val = warpPrefixSum[gl_SubgroupInvocationID]; uint val = warpPrefixSum[gl_SubgroupInvocationID];
subgroupBarrier(); subgroupBarrier();
//Use warp to do entire add in 1 reduction //Use warp to do entire add in 1 reduction
warpPrefixSum[gl_SubgroupInvocationID] = subgroupExclusiveAdd(val); warpPrefixSum[gl_SubgroupInvocationID] = subgroupExclusiveAdd(val);
} }
#endif
barrier(); barrier();
//Add the computed sum across all threads and warps //Add the computed sum across all threads and warps