BB
This commit is contained in:
@@ -38,7 +38,7 @@ public class ModelBakerySubsystem {
|
|||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
//There should be a method to access the frame time IIRC, if the user framecap is unlimited lock it to like 60 fps for computation
|
//There should be a method to access the frame time IIRC, if the user framecap is unlimited lock it to like 60 fps for computation
|
||||||
int BUDGET = 10;//TODO: make this computed based on the remaining free time in a frame (and like div by 2 to reduce overhead) (with a min of 1)
|
int BUDGET = 20;//TODO: make this computed based on the remaining free time in a frame (and like div by 2 to reduce overhead) (with a min of 1)
|
||||||
|
|
||||||
for (int i = 0; i < BUDGET && !this.blockIdQueue.isEmpty(); i++) {
|
for (int i = 0; i < BUDGET && !this.blockIdQueue.isEmpty(); i++) {
|
||||||
int blockId = -1;
|
int blockId = -1;
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package me.cortex.voxy.client.core.rendering;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
|
import me.cortex.voxy.client.core.rendering.building.BuiltSection;
|
||||||
|
|
||||||
|
//CPU side cache for section geometry, not thread safe
|
||||||
|
public class GeometryCache {
|
||||||
|
private long maxCombinedSize;
|
||||||
|
private long currentSize;
|
||||||
|
private final Long2ObjectLinkedOpenHashMap<BuiltSection> cache = new Long2ObjectLinkedOpenHashMap<>();
|
||||||
|
public GeometryCache(long maxSize) {
|
||||||
|
this.maxCombinedSize = maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Puts the section into the cache
|
||||||
|
public void put(BuiltSection section) {
|
||||||
|
var prev = this.cache.put(section.position, section);
|
||||||
|
this.currentSize += section.geometryBuffer.size;
|
||||||
|
if (prev != null) {
|
||||||
|
this.currentSize -= prev.geometryBuffer.size;
|
||||||
|
prev.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (this.maxCombinedSize <= this.currentSize) {
|
||||||
|
var entry = this.cache.removeFirst();
|
||||||
|
this.currentSize -= entry.geometryBuffer.size;
|
||||||
|
entry.free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuiltSection remove(long position) {
|
||||||
|
var section = this.cache.remove(position);
|
||||||
|
if (section != null) {
|
||||||
|
this.currentSize -= section.geometryBuffer.size;
|
||||||
|
}
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,7 +47,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
|
|
||||||
//Max sections: ~500k
|
//Max sections: ~500k
|
||||||
//Max geometry: 1 gb
|
//Max geometry: 1 gb
|
||||||
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<19, (1L<<30)-1024);
|
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<19, (1L<<31)-1024);
|
||||||
|
|
||||||
//Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard
|
//Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard
|
||||||
var router = new SectionUpdateRouter();
|
var router = new SectionUpdateRouter();
|
||||||
@@ -69,7 +69,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
this.sectionUpdateQueue.push(section);
|
this.sectionUpdateQueue.push(section);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.traversal = new HierarchicalOcclusionTraverser(this.nodeManager, 256);
|
this.traversal = new HierarchicalOcclusionTraverser(this.nodeManager);
|
||||||
|
|
||||||
world.setDirtyCallback(router::forward);
|
world.setDirtyCallback(router::forward);
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(0, 0,0,0));
|
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(0, 0,0,0));
|
||||||
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0));
|
//this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0));
|
||||||
|
|
||||||
/*
|
|
||||||
final int H_WIDTH = 10;
|
final int H_WIDTH = 10;
|
||||||
for (int x = -H_WIDTH; x <= H_WIDTH; x++) {
|
for (int x = -H_WIDTH; x <= H_WIDTH; x++) {
|
||||||
for (int y = -1; y <= 0; y++) {
|
for (int y = -1; y <= 0; y++) {
|
||||||
@@ -87,7 +87,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
|||||||
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z));
|
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup(Camera camera) {
|
public void setup(Camera camera) {
|
||||||
|
|||||||
@@ -28,9 +28,10 @@ import static org.lwjgl.opengl.GL45.*;
|
|||||||
|
|
||||||
// TODO: swap to persistent gpu threads instead of dispatching MAX_ITERATIONS of compute layers
|
// TODO: swap to persistent gpu threads instead of dispatching MAX_ITERATIONS of compute layers
|
||||||
public class HierarchicalOcclusionTraverser {
|
public class HierarchicalOcclusionTraverser {
|
||||||
|
public static final int REQUEST_QUEUE_SIZE = 256;
|
||||||
|
|
||||||
private final NodeManager2 nodeManager;
|
private final NodeManager2 nodeManager;
|
||||||
|
|
||||||
private final int maxRequestCount;
|
|
||||||
private final GlBuffer requestBuffer;
|
private final GlBuffer requestBuffer;
|
||||||
|
|
||||||
private final GlBuffer nodeBuffer;
|
private final GlBuffer nodeBuffer;
|
||||||
@@ -61,7 +62,7 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
.defineIf("DEBUG", Voxy.SHADER_DEBUG)
|
.defineIf("DEBUG", Voxy.SHADER_DEBUG)
|
||||||
.define("MAX_ITERATIONS", MAX_ITERATIONS)
|
.define("MAX_ITERATIONS", MAX_ITERATIONS)
|
||||||
.define("LOCAL_SIZE_BITS", LOCAL_WORK_SIZE_BITS)
|
.define("LOCAL_SIZE_BITS", LOCAL_WORK_SIZE_BITS)
|
||||||
.define("REQUEST_QUEUE_SIZE", NodeManager.REQUEST_QUEUE_SIZE)
|
.define("REQUEST_QUEUE_SIZE", REQUEST_QUEUE_SIZE)
|
||||||
|
|
||||||
.define("HIZ_BINDING", 0)
|
.define("HIZ_BINDING", 0)
|
||||||
|
|
||||||
@@ -79,11 +80,10 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
|
|
||||||
public HierarchicalOcclusionTraverser(NodeManager2 nodeManager, int requestBufferCount) {
|
public HierarchicalOcclusionTraverser(NodeManager2 nodeManager) {
|
||||||
this.nodeManager = nodeManager;
|
this.nodeManager = nodeManager;
|
||||||
this.requestBuffer = new GlBuffer(requestBufferCount*8L+8).zero();
|
this.requestBuffer = new GlBuffer(REQUEST_QUEUE_SIZE*8L+8).zero();
|
||||||
this.nodeBuffer = new GlBuffer(nodeManager.maxNodeCount*16L).zero();
|
this.nodeBuffer = new GlBuffer(nodeManager.maxNodeCount*16L).zero();
|
||||||
this.maxRequestCount = requestBufferCount;
|
|
||||||
|
|
||||||
|
|
||||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
glSamplerParameteri(this.hizSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||||
@@ -245,8 +245,8 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
Logger.warn("Count over max buffer size, clamping, got count: " + count);
|
Logger.warn("Count over max buffer size, clamping, got count: " + count);
|
||||||
count = (int) ((this.requestBuffer.size()>>3)-1);
|
count = (int) ((this.requestBuffer.size()>>3)-1);
|
||||||
}
|
}
|
||||||
if (count > this.maxRequestCount) {
|
if (count > REQUEST_QUEUE_SIZE) {
|
||||||
System.err.println("Count larger than 'maxRequestCount', overflow captured. Overflowed by " + (count-this.maxRequestCount));
|
System.err.println("Count larger than 'maxRequestCount', overflow captured. Overflowed by " + (count-REQUEST_QUEUE_SIZE));
|
||||||
}
|
}
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
//this.nodeManager.processRequestQueue(count, ptr + 8);
|
//this.nodeManager.processRequestQueue(count, ptr + 8);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class VoxyCommon implements ModInitializer {
|
|||||||
|
|
||||||
|
|
||||||
//This is hardcoded like this because people do not understand what they are doing
|
//This is hardcoded like this because people do not understand what they are doing
|
||||||
private static final boolean GlobalVerificationDisableOverride = false;//System.getProperty("voxy.verificationDisableOverride", "false").equals("true");
|
private static final boolean GlobalVerificationDisableOverride = true;//System.getProperty("voxy.verificationDisableOverride", "false").equals("true");
|
||||||
public static boolean isVerificationFlagOn(String name) {
|
public static boolean isVerificationFlagOn(String name) {
|
||||||
return (!GlobalVerificationDisableOverride) && System.getProperty("voxy."+name, "true").equals("true");
|
return (!GlobalVerificationDisableOverride) && System.getProperty("voxy."+name, "true").equals("true");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ layout(location = 0) in vec2 uv;
|
|||||||
layout(binding = 0) uniform sampler2D depthTex;
|
layout(binding = 0) uniform sampler2D depthTex;
|
||||||
void main() {
|
void main() {
|
||||||
vec4 depths = textureGather(depthTex, uv, 0); // Get depth values from all surrounding texels.
|
vec4 depths = textureGather(depthTex, uv, 0); // Get depth values from all surrounding texels.
|
||||||
//depths = mix(vec4(0), depths, lessThanEqual(vec4(0.99999999), depths));
|
bvec4 cv = lessThanEqual(vec4(0.99999999), depths);
|
||||||
|
if (any(cv) && !all(cv)) {
|
||||||
|
depths = mix(vec4(0), depths, cv);
|
||||||
|
}
|
||||||
gl_FragDepth = max(max(depths.x, depths.y), max(depths.z, depths.w)); // Write conservative depth.
|
gl_FragDepth = max(max(depths.x, depths.y), max(depths.z, depths.w)); // Write conservative depth.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ vec3 minBB;
|
|||||||
vec3 maxBB;
|
vec3 maxBB;
|
||||||
vec2 size;
|
vec2 size;
|
||||||
|
|
||||||
uint lod;
|
|
||||||
|
|
||||||
//Sets up screenspace with the given node id, returns true on success false on failure/should not continue
|
//Sets up screenspace with the given node id, returns true on success false on failure/should not continue
|
||||||
//Accesses data that is setup in the main traversal and is just shared to here
|
//Accesses data that is setup in the main traversal and is just shared to here
|
||||||
void setupScreenspace(in UnpackedNode node) {
|
void setupScreenspace(in UnpackedNode node) {
|
||||||
@@ -35,7 +33,6 @@ void setupScreenspace(in UnpackedNode node) {
|
|||||||
vec3 point = VP*(((transform.transform*vec4((node.pos<<node.lodLevel) - transform.originPos.xyz, 1))
|
vec3 point = VP*(((transform.transform*vec4((node.pos<<node.lodLevel) - transform.originPos.xyz, 1))
|
||||||
+ (transform.worldPos.xyz-camChunkPos))-camSubChunk);
|
+ (transform.worldPos.xyz-camChunkPos))-camSubChunk);
|
||||||
*/
|
*/
|
||||||
lod = node.lodLevel;
|
|
||||||
|
|
||||||
vec4 base = VP*vec4(vec3(((node.pos<<node.lodLevel)-camSecPos)<<5)-camSubSecPos, 1);
|
vec4 base = VP*vec4(vec3(((node.pos<<node.lodLevel)-camSecPos)<<5)-camSubSecPos, 1);
|
||||||
|
|
||||||
@@ -86,10 +83,10 @@ bool isCulledByHiz() {
|
|||||||
float miplevel = ceil(log2(max(max(ssize.x, ssize.y),1)));
|
float miplevel = ceil(log2(max(max(ssize.x, ssize.y),1)));
|
||||||
vec2 midpoint = (maxBB.xy + minBB.xy)*0.5f;
|
vec2 midpoint = (maxBB.xy + minBB.xy)*0.5f;
|
||||||
bool culled = textureLod(hizDepthSampler, vec3(midpoint, minBB.z), miplevel) < 0.0001f;
|
bool culled = textureLod(hizDepthSampler, vec3(midpoint, minBB.z), miplevel) < 0.0001f;
|
||||||
/*
|
|
||||||
if (culled) {
|
if (culled) {
|
||||||
printf("HiZ sample point not culled: (%f,%f)@%f against %f, level %d", midpoint.x, midpoint.y, miplevel, minBB.z, lod);
|
printf("HiZ sample point culled: (%f,%f)@%f against %f", midpoint.x, midpoint.y, miplevel, minBB.z);
|
||||||
}*/
|
}
|
||||||
return culled;
|
return culled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user