Add support for FREX flawless frames, failed attempt to fix intel igpus
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user