Continue work on adding node cleaner support
This commit is contained in:
@@ -195,6 +195,9 @@ public class ChunkBoundRenderer {
|
|||||||
|
|
||||||
private void ensureSize1() {
|
private void ensureSize1() {
|
||||||
if (this.chunk2idx.size() < this.idx2chunk.length) return;
|
if (this.chunk2idx.size() < this.idx2chunk.length) return;
|
||||||
|
//Commit any copies, ensures is synced to new buffer
|
||||||
|
UploadStream.INSTANCE.commit();
|
||||||
|
|
||||||
int size = (int) (this.idx2chunk.length*1.5);
|
int size = (int) (this.idx2chunk.length*1.5);
|
||||||
Logger.info("Resizing chunk position buffer to: " + size);
|
Logger.info("Resizing chunk position buffer to: " + size);
|
||||||
//Need to resize
|
//Need to resize
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, Q>, J extends Vi
|
|||||||
//Tick download stream
|
//Tick download stream
|
||||||
DownloadStream.INSTANCE.tick();
|
DownloadStream.INSTANCE.tick();
|
||||||
|
|
||||||
this.nodeManager.tick(this.traversal.getNodeBuffer());
|
this.nodeManager.tick(this.traversal.getNodeBuffer(), this.nodeCleaner);
|
||||||
//glFlush();
|
//glFlush();
|
||||||
|
|
||||||
this.nodeCleaner.tick(this.traversal.getNodeBuffer());//Probably do this here??
|
this.nodeCleaner.tick(this.traversal.getNodeBuffer());//Probably do this here??
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ public class AsyncNodeManager {
|
|||||||
|
|
||||||
//locals for during iteration
|
//locals for during iteration
|
||||||
private final IntOpenHashSet tlnIdChange = new IntOpenHashSet();//"Encoded" add/remove id, first bit indicates if its add or remove, 1 is add
|
private final IntOpenHashSet tlnIdChange = new IntOpenHashSet();//"Encoded" add/remove id, first bit indicates if its add or remove, 1 is add
|
||||||
|
//Top bit indicates clear or reset
|
||||||
|
private final IntOpenHashSet cleanerIdResetClear = new IntOpenHashSet();//Tells the cleaner if it needs to clear the id to 0, or reset the id to the current frame
|
||||||
|
|
||||||
private boolean needsWaitForSync = false;
|
private boolean needsWaitForSync = false;
|
||||||
|
|
||||||
public AsyncNodeManager(int maxNodeCount, ISectionWatcher watcher, IGeometryData geometryData) {
|
public AsyncNodeManager(int maxNodeCount, ISectionWatcher watcher, IGeometryData geometryData) {
|
||||||
@@ -98,20 +101,23 @@ public class AsyncNodeManager {
|
|||||||
|
|
||||||
this.geometryManager = new BasicAsyncGeometryManager(((BasicSectionGeometryData)geometryData).getMaxSectionCount(), ((BasicSectionGeometryData)geometryData).getGeometryCapacity());
|
this.geometryManager = new BasicAsyncGeometryManager(((BasicSectionGeometryData)geometryData).getMaxSectionCount(), ((BasicSectionGeometryData)geometryData).getGeometryCapacity());
|
||||||
this.manager = new NodeManager(maxNodeCount, this.geometryManager, watcher);
|
this.manager = new NodeManager(maxNodeCount, this.geometryManager, watcher);
|
||||||
|
//Dont do the move... is just to much effort
|
||||||
this.manager.setClear(new NodeManager.ICleaner() {
|
this.manager.setClear(new NodeManager.ICleaner() {
|
||||||
@Override
|
@Override
|
||||||
public void alloc(int id) {
|
public void alloc(int id) {
|
||||||
|
AsyncNodeManager.this.cleanerIdResetClear.remove(id);//Remove clear
|
||||||
|
AsyncNodeManager.this.cleanerIdResetClear.add(id|(1<<31));//Add reset
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void move(int from, int to) {
|
public void move(int from, int to) {
|
||||||
|
//noop (sorry :( will cause some perf loss/incorrect cleaning )
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void free(int id) {
|
public void free(int id) {
|
||||||
|
AsyncNodeManager.this.cleanerIdResetClear.remove(id|(1<<31));//Remove reset
|
||||||
|
AsyncNodeManager.this.cleanerIdResetClear.add(id);//Add clear
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.manager.setTLNCallbacks(id->{
|
this.manager.setTLNCallbacks(id->{
|
||||||
@@ -353,6 +359,7 @@ public class AsyncNodeManager {
|
|||||||
results.geometryUploads.putAll(this.geometryManager.getUploads());
|
results.geometryUploads.putAll(this.geometryManager.getUploads());
|
||||||
this.geometryManager.getUploads().clear();//Put in new data into sync set
|
this.geometryManager.getUploads().clear();//Put in new data into sync set
|
||||||
this.geometryManager.getHeapRemovals().clear();//We dont do removals on new data (as there is "none")
|
this.geometryManager.getHeapRemovals().clear();//We dont do removals on new data (as there is "none")
|
||||||
|
results.cleanerOperations.addAll(this.cleanerIdResetClear); this.cleanerIdResetClear.clear();
|
||||||
} else {
|
} else {
|
||||||
results = prev;
|
results = prev;
|
||||||
// merge with the previous result set
|
// merge with the previous result set
|
||||||
@@ -368,6 +375,16 @@ public class AsyncNodeManager {
|
|||||||
this.tlnIdChange.clear();
|
this.tlnIdChange.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.cleanerIdResetClear.isEmpty()) {//Merge top level node id changes
|
||||||
|
var iter = this.cleanerIdResetClear.intIterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
int val = iter.nextInt();
|
||||||
|
results.cleanerOperations.remove(val^(1<<31));//Remove opposite
|
||||||
|
results.cleanerOperations.add(val);//Add this
|
||||||
|
}
|
||||||
|
this.cleanerIdResetClear.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.geometryManager.getHeapRemovals().isEmpty()) {//Remove and free all the removed geometry uploads
|
if (!this.geometryManager.getHeapRemovals().isEmpty()) {//Remove and free all the removed geometry uploads
|
||||||
var rem = this.geometryManager.getHeapRemovals();
|
var rem = this.geometryManager.getHeapRemovals();
|
||||||
var iter = rem.intIterator();
|
var iter = rem.intIterator();
|
||||||
@@ -440,7 +457,7 @@ public class AsyncNodeManager {
|
|||||||
|
|
||||||
private IntConsumer tlnAddCallback; private IntConsumer tlnRemoveCallback;
|
private IntConsumer tlnAddCallback; private IntConsumer tlnRemoveCallback;
|
||||||
//Render thread synchronization
|
//Render thread synchronization
|
||||||
public void tick(GlBuffer nodeBuffer) {//TODO: dont pass nodeBuffer here??, do something else thats better
|
public void tick(GlBuffer nodeBuffer, NodeCleaner cleaner) {//TODO: dont pass nodeBuffer here??, do something else thats better
|
||||||
var results = (SyncResults)RESULT_HANDLE.getAndSet(this, null);//Acquire the results
|
var results = (SyncResults)RESULT_HANDLE.getAndSet(this, null);//Acquire the results
|
||||||
if (results == null) {//There are no new results to process, return
|
if (results == null) {//There are no new results to process, return
|
||||||
return;
|
return;
|
||||||
@@ -498,6 +515,12 @@ public class AsyncNodeManager {
|
|||||||
glMemoryBarrier(GL_UNIFORM_BARRIER_BIT|GL_SHADER_STORAGE_BARRIER_BIT);
|
glMemoryBarrier(GL_UNIFORM_BARRIER_BIT|GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!results.cleanerOperations.isEmpty()) {
|
||||||
|
cleaner.updateIds(results.cleanerOperations);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentMaxNodeId = results.currentMaxNodeId;
|
||||||
|
|
||||||
//Insert the result set into the cache
|
//Insert the result set into the cache
|
||||||
if (!RESULT_CACHE_1_HANDLE.compareAndSet(this, null, results)) {
|
if (!RESULT_CACHE_1_HANDLE.compareAndSet(this, null, results)) {
|
||||||
//Failed to insert into result set 1, insert it into result set 2
|
//Failed to insert into result set 1, insert it into result set 2
|
||||||
@@ -513,6 +536,11 @@ public class AsyncNodeManager {
|
|||||||
this.tlnRemoveCallback = remove;
|
this.tlnRemoveCallback = remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int currentMaxNodeId = 0;
|
||||||
|
public int getCurrentMaxNodeId() {
|
||||||
|
return this.currentMaxNodeId;
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================================
|
//==================================================================================================================
|
||||||
//Incoming events
|
//Incoming events
|
||||||
|
|
||||||
@@ -679,11 +707,15 @@ public class AsyncNodeManager {
|
|||||||
private MemoryBuffer scatterWriteBuffer = new MemoryBuffer(8192*2);
|
private MemoryBuffer scatterWriteBuffer = new MemoryBuffer(8192*2);
|
||||||
private final Int2IntOpenHashMap scatterWriteLocationMap = new Int2IntOpenHashMap(1024);
|
private final Int2IntOpenHashMap scatterWriteLocationMap = new Int2IntOpenHashMap(1024);
|
||||||
|
|
||||||
|
//Cleaner operations
|
||||||
|
private final IntOpenHashSet cleanerOperations = new IntOpenHashSet();
|
||||||
|
|
||||||
public SyncResults() {
|
public SyncResults() {
|
||||||
this.scatterWriteLocationMap.defaultReturnValue(-1);
|
this.scatterWriteLocationMap.defaultReturnValue(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
|
this.cleanerOperations.clear();
|
||||||
this.scatterWriteLocationMap.clear();
|
this.scatterWriteLocationMap.clear();
|
||||||
this.currentMaxNodeId = 0;
|
this.currentMaxNodeId = 0;
|
||||||
this.tlnDelta.clear();
|
this.tlnDelta.clear();
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ public class NodeCleaner {
|
|||||||
static final int OUTPUT_COUNT = 256;
|
static final int OUTPUT_COUNT = 256;
|
||||||
|
|
||||||
|
|
||||||
private static final int BATCH_SET_SIZE = 2048;
|
|
||||||
|
|
||||||
|
|
||||||
private final AutoBindingShader sorter = Shader.makeAuto(PrintfDebugUtil.PRINTF_processor)
|
private final AutoBindingShader sorter = Shader.makeAuto(PrintfDebugUtil.PRINTF_processor)
|
||||||
.define("WORK_SIZE", SORTING_WORKER_SIZE)
|
.define("WORK_SIZE", SORTING_WORKER_SIZE)
|
||||||
.define("ELEMS_PER_THREAD", WORK_PER_THREAD)
|
.define("ELEMS_PER_THREAD", WORK_PER_THREAD)
|
||||||
@@ -63,10 +60,6 @@ public class NodeCleaner {
|
|||||||
|
|
||||||
final GlBuffer visibilityBuffer;
|
final GlBuffer visibilityBuffer;
|
||||||
private final GlBuffer outputBuffer = new GlBuffer(OUTPUT_COUNT*4+OUTPUT_COUNT*8);//Scratch + output
|
private final GlBuffer outputBuffer = new GlBuffer(OUTPUT_COUNT*4+OUTPUT_COUNT*8);//Scratch + output
|
||||||
private final GlBuffer scratchBuffer = new GlBuffer(BATCH_SET_SIZE*4);//Scratch buffer for setting ids with
|
|
||||||
|
|
||||||
private final IntOpenHashSet allocIds = new IntOpenHashSet();
|
|
||||||
private final IntOpenHashSet freeIds = new IntOpenHashSet();
|
|
||||||
|
|
||||||
private final AsyncNodeManager nodeManager;
|
private final AsyncNodeManager nodeManager;
|
||||||
int visibilityId = 0;
|
int visibilityId = 0;
|
||||||
@@ -78,8 +71,7 @@ public class NodeCleaner {
|
|||||||
this.visibilityBuffer.fill(-1);
|
this.visibilityBuffer.fill(-1);
|
||||||
|
|
||||||
this.batchClear
|
this.batchClear
|
||||||
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer)
|
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer);
|
||||||
.ssbo("LIST_BUFFER_BINDING", this.scratchBuffer);
|
|
||||||
|
|
||||||
this.sorter
|
this.sorter
|
||||||
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer)
|
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer)
|
||||||
@@ -111,10 +103,6 @@ public class NodeCleaner {
|
|||||||
|
|
||||||
public void tick(GlBuffer nodeDataBuffer) {
|
public void tick(GlBuffer nodeDataBuffer) {
|
||||||
this.visibilityId++;
|
this.visibilityId++;
|
||||||
|
|
||||||
this.setIds(this.allocIds, this.visibilityId);
|
|
||||||
this.setIds(this.freeIds, -1);
|
|
||||||
|
|
||||||
if (this.shouldCleanGeometry()) {
|
if (this.shouldCleanGeometry()) {
|
||||||
this.outputBuffer.fill(this.nodeManager.maxNodeCount - 2);//TODO: maybe dont set to zero??
|
this.outputBuffer.fill(this.nodeManager.maxNodeCount - 2);//TODO: maybe dont set to zero??
|
||||||
|
|
||||||
@@ -124,7 +112,7 @@ public class NodeCleaner {
|
|||||||
//TODO: choose whether this is in nodeSpace or section/geometryId space
|
//TODO: choose whether this is in nodeSpace or section/geometryId space
|
||||||
//
|
//
|
||||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
//glDispatchCompute((this.nodeManager.getCurrentMaxNodeId() + (SORTING_WORKER_SIZE+WORK_PER_THREAD) - 1) / (SORTING_WORKER_SIZE+WORK_PER_THREAD), 1, 1);
|
glDispatchCompute((this.nodeManager.getCurrentMaxNodeId() + (SORTING_WORKER_SIZE+WORK_PER_THREAD) - 1) / (SORTING_WORKER_SIZE+WORK_PER_THREAD), 1, 1);
|
||||||
|
|
||||||
this.resultTransformer.bind();
|
this.resultTransformer.bind();
|
||||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, this.outputBuffer.id, 0, 4 * OUTPUT_COUNT);
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, this.outputBuffer.id, 0, 4 * OUTPUT_COUNT);
|
||||||
@@ -151,22 +139,26 @@ public class NodeCleaner {
|
|||||||
return false;//return 3<((double)this.nodeManager.getGeometryManager().getUsedCapacity())/((double)this.nodeManager.getGeometryManager().getRemainingCapacity());
|
return false;//return 3<((double)this.nodeManager.getGeometryManager().getUsedCapacity())/((double)this.nodeManager.getGeometryManager().getRemainingCapacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIds(IntOpenHashSet collection, int setTo) {
|
public void updateIds(IntOpenHashSet collection) {
|
||||||
if (!collection.isEmpty()) {
|
if (!collection.isEmpty()) {
|
||||||
this.batchClear.bind();
|
int count = collection.size();
|
||||||
|
long addr = UploadStream.INSTANCE.rawUploadAddress(count * 4 + 16);//TODO ensure alignment, create method todo alignment things
|
||||||
|
addr = (addr+15)&~15L;//Align to 16 bytes
|
||||||
|
|
||||||
|
long ptr = UploadStream.INSTANCE.getBaseAddress() + addr;
|
||||||
var iter = collection.iterator();
|
var iter = collection.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
int cnt = Math.min(collection.size(), BATCH_SET_SIZE);
|
MemoryUtil.memPutInt(ptr, iter.nextInt()); ptr+=4;
|
||||||
long ptr = UploadStream.INSTANCE.upload(this.scratchBuffer, 0, cnt * 4L);
|
|
||||||
for (int i = 0; i < cnt; i++) {
|
|
||||||
MemoryUtil.memPutInt(ptr + i * 4, iter.nextInt());
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
UploadStream.INSTANCE.commit();
|
|
||||||
glUniform1ui(0, cnt);
|
|
||||||
glUniform1ui(1, setTo);
|
|
||||||
glDispatchCompute((cnt+127)/128, 1, 1);
|
|
||||||
}
|
}
|
||||||
|
UploadStream.INSTANCE.commit();
|
||||||
|
|
||||||
|
this.batchClear.bind();
|
||||||
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, UploadStream.INSTANCE.getRawBufferId(), addr, count*4L);
|
||||||
|
glUniform1ui(0, count);
|
||||||
|
glUniform1ui(1, this.visibilityId);
|
||||||
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
glDispatchCompute((count+127)/128, 1, 1);
|
||||||
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +166,6 @@ public class NodeCleaner {
|
|||||||
this.sorter.free();
|
this.sorter.free();
|
||||||
this.visibilityBuffer.free();
|
this.visibilityBuffer.free();
|
||||||
this.outputBuffer.free();
|
this.outputBuffer.free();
|
||||||
this.scratchBuffer.free();
|
|
||||||
this.batchClear.free();
|
this.batchClear.free();
|
||||||
this.resultTransformer.free();
|
this.resultTransformer.free();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ void main() {
|
|||||||
if (count <= id) {
|
if (count <= id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visiblity[ids[id]] = setTo;
|
uint pos = ids[id];
|
||||||
|
visiblity[pos&((1u<<31)-1)] = mix(setTo, uint(-1), (pos&(1u<<31)) == 0);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user