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.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
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 {
private static final HashSet<String> FREX = new HashSet<>();
@Override
public void onInitializeClient() {
ClientLifecycleEvents.CLIENT_STARTED.register(client->{
boolean systemSupported = Capabilities.INSTANCE.compute && Capabilities.INSTANCE.indirectParameters;
if (systemSupported) {
@@ -26,5 +32,17 @@ public class VoxyClient implements ClientModInitializer {
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.systems.RenderSystem;
import me.cortex.voxy.client.TimingStatistics;
import me.cortex.voxy.client.VoxyClient;
import me.cortex.voxy.client.config.VoxyConfig;
import me.cortex.voxy.client.core.gl.Capabilities;
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)
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
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 boolean compute;
public final boolean indirectParameters;
public final boolean isIntel;
public Capabilities() {
var cap = GL.getCapabilities();
this.compute = cap.glDispatchComputeIndirect != 0;
@@ -42,6 +44,7 @@ public class Capabilities {
this.ssboMaxSize = glGetInteger64(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
this.isMesa = glGetString(GL_VERSION).toLowerCase().contains("mesa");
this.isIntel = glGetString(GL_VENDOR).toLowerCase().contains("intel");
if (this.canQueryGpuMemory) {
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;
import me.cortex.voxy.client.core.gl.Capabilities;
import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.GlDebug;
import me.cortex.voxy.common.Logger;
@@ -147,6 +148,7 @@ public class Shader extends TrackedObject {
}
public T compile() {
this.defineIf("IS_INTEL", Capabilities.INSTANCE.isIntel);
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
}
public void setCenterAndProcess(double x, double z) {
public boolean setCenterAndProcess(double x, double z) {
double dx = this.posX-x;
double dz = this.posZ-z;
if (CHECK_DISTANCE_BLOCKS*CHECK_DISTANCE_BLOCKS<dx*dx+dz*dz) {
@@ -43,7 +43,7 @@ public class RenderDistanceTracker {
this.posZ = z;
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) {

View File

@@ -2,6 +2,7 @@ package me.cortex.voxy.client.core.rendering;
import me.cortex.voxy.client.RenderStatistics;
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.GlTexture;
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.MDICSectionRenderer;
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.world.WorldEngine;
import me.cortex.voxy.common.thread.ServiceThreadPool;
@@ -117,18 +119,12 @@ public class RenderService<T extends AbstractSectionRenderer<J, Q>, J extends Vi
this.sectionRenderer.renderOpaque(viewport, depthBoundTexture);
TimingStatistics.G.stop();
//NOTE: need to do the upload and download tick here, after the section renderer renders the world, to ensure "stable"
// 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.dynamic.start();
do {
//NOTE: need to do the upload and download tick here, after the section renderer renders the world, to ensure "stable"
// sections
{
TimingStatistics.main.stop();
TimingStatistics.dynamic.start();
/*
this.sectionUpdateQueue.consume(128);
@@ -143,29 +139,40 @@ public class RenderService<T extends AbstractSectionRenderer<J, Q>, J extends Vi
}*/
TimingStatistics.D.start();
//Tick download stream
DownloadStream.INSTANCE.tick();
TimingStatistics.D.stop();
TimingStatistics.D.start();
//Tick download stream
DownloadStream.INSTANCE.tick();
TimingStatistics.D.stop();
this.nodeManager.tick(this.traversal.getNodeBuffer(), this.nodeCleaner);
//glFlush();
this.nodeManager.tick(this.traversal.getNodeBuffer(), this.nodeCleaner);
//glFlush();
this.nodeCleaner.tick(this.traversal.getNodeBuffer());//Probably do this here??
this.nodeCleaner.tick(this.traversal.getNodeBuffer());//Probably do this here??
TimingStatistics.dynamic.stop();
TimingStatistics.main.start();
}
TimingStatistics.dynamic.stop();
TimingStatistics.main.start();
}
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT|GL_PIXEL_BUFFER_BARRIER_BIT);
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_PIXEL_BUFFER_BARRIER_BIT);
int depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
if (depthBuffer == 0) {
depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
}
TimingStatistics.I.start();
this.traversal.doTraversal(viewport, depthBuffer);
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()));
int depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
if (depthBuffer == 0) {
depthBuffer = glGetFramebufferAttachmentParameteri(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
}
TimingStatistics.I.start();
this.traversal.doTraversal(viewport, depthBuffer);
TimingStatistics.I.stop();
TimingStatistics.H.start();
this.sectionRenderer.buildDrawCalls(viewport);

View File

@@ -717,6 +717,10 @@ public class AsyncNodeManager {
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
private static final class SyncResults {
//Contains

View File

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