mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-14 14:33:57 +01:00
Bookkeeping
- Mappings drop pages when they write zero validity bits - Instancer only updates pages that changed
This commit is contained in:
parent
20b3f78b9c
commit
fac63168c1
@ -168,7 +168,7 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
|||||||
int otherValid = other.valid.get();
|
int otherValid = other.valid.get();
|
||||||
|
|
||||||
// If the other page is empty, or we're full, we're done.
|
// If the other page is empty, or we're full, we're done.
|
||||||
if (otherValid == 0 || valid == 0xFFFFFFFF) {
|
if (isEmpty(otherValid) || isFull(valid)) {
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,15 +223,27 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
|||||||
public void update(int modelIndex, int baseInstance) {
|
public void update(int modelIndex, int baseInstance) {
|
||||||
this.baseInstance = baseInstance;
|
this.baseInstance = baseInstance;
|
||||||
|
|
||||||
if (this.modelIndex == modelIndex && changedPages.isEmpty()) {
|
var sameModelIndex = this.modelIndex == modelIndex;
|
||||||
|
if (sameModelIndex && changedPages.isEmpty()) {
|
||||||
|
// Nothing to do!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modelIndex = modelIndex;
|
this.modelIndex = modelIndex;
|
||||||
|
|
||||||
var pages = this.pages.get();
|
var pages = this.pages.get();
|
||||||
mapping.updateCount(pages.length);
|
mapping.updateCount(pages.length);
|
||||||
|
|
||||||
for (int i = 0; i < pages.length; i++) {
|
if (sameModelIndex) {
|
||||||
mapping.updatePage(i, modelIndex, pages[i].valid.get());
|
// Only need to update the changed pages.
|
||||||
|
for (int page = changedPages.nextSetBit(0); page >= 0 && page < pages.length; page = changedPages.nextSetBit(page + 1)) {
|
||||||
|
mapping.updatePage(page, modelIndex, pages[page].valid.get());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Need to update all pages since the model index changed.
|
||||||
|
for (int i = 0; i < pages.length; i++) {
|
||||||
|
mapping.updatePage(i, modelIndex, pages[i].valid.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,46 +303,17 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void parallelUpdate() {
|
public void parallelUpdate() {
|
||||||
if (true) {
|
// TODO: Merge pages when they're less than half full.
|
||||||
// FIXME: infinite loop when the page in readpos doesn't have enough to fill the page in writepos
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pages = this.pages.get();
|
|
||||||
|
|
||||||
// If there are at least 2 pages with space, we can consolidate.
|
|
||||||
if (fullPages.cardinality() > (pages.length - 2)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note this runs after visuals are updated so we don't really have to take care for thread safety.
|
|
||||||
|
|
||||||
int writePos = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
writePos = fullPages.nextClearBit(writePos);
|
|
||||||
int readPos = fullPages.nextClearBit(writePos + 1);
|
|
||||||
|
|
||||||
if (writePos >= pages.length || readPos >= pages.length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
InstancePage writeTo = pages[writePos];
|
|
||||||
InstancePage readFrom = pages[readPos];
|
|
||||||
|
|
||||||
int validNow = writeTo.takeFrom(readFrom);
|
|
||||||
|
|
||||||
if (isFull(validNow)) {
|
|
||||||
fullPages.set(writePos);
|
|
||||||
writePos = readPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFull(int valid) {
|
private static boolean isFull(int valid) {
|
||||||
return valid == 0xFFFFFFFF;
|
return valid == 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isEmpty(int otherValid) {
|
||||||
|
return otherValid == 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete() {
|
public void delete() {
|
||||||
for (IndirectDraw draw : draws()) {
|
for (IndirectDraw draw : draws()) {
|
||||||
|
@ -13,6 +13,8 @@ public class ObjectStorage extends AbstractArena {
|
|||||||
public static final int PAGE_SIZE = 1 << LOG_2_PAGE_SIZE;
|
public static final int PAGE_SIZE = 1 << LOG_2_PAGE_SIZE;
|
||||||
public static final int PAGE_MASK = PAGE_SIZE - 1;
|
public static final int PAGE_MASK = PAGE_SIZE - 1;
|
||||||
|
|
||||||
|
public static final int INVALID_PAGE = -1;
|
||||||
|
|
||||||
public static final int INITIAL_PAGES_ALLOCATED = 4;
|
public static final int INITIAL_PAGES_ALLOCATED = 4;
|
||||||
public static final int DESCRIPTOR_SIZE_BYTES = Integer.BYTES * 2;
|
public static final int DESCRIPTOR_SIZE_BYTES = Integer.BYTES * 2;
|
||||||
|
|
||||||
@ -53,8 +55,13 @@ public class ObjectStorage extends AbstractArena {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void free(int i) {
|
public void free(int i) {
|
||||||
|
if (i == INVALID_PAGE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
super.free(i);
|
super.free(i);
|
||||||
MemoryUtil.memPutInt(ptrForPage(i), 0);
|
var ptr = ptrForPage(i);
|
||||||
|
MemoryUtil.memPutInt(ptr, 0);
|
||||||
|
MemoryUtil.memPutInt(ptr + 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -98,14 +105,49 @@ public class ObjectStorage extends AbstractArena {
|
|||||||
private static final int[] EMPTY_ALLOCATION = new int[0];
|
private static final int[] EMPTY_ALLOCATION = new int[0];
|
||||||
private int[] pages = EMPTY_ALLOCATION;
|
private int[] pages = EMPTY_ALLOCATION;
|
||||||
|
|
||||||
public void updatePage(int i, int modelIndex, int i1) {
|
public void updatePage(int index, int modelIndex, int validBits) {
|
||||||
var ptr = ptrForPage(pages[i]);
|
if (validBits == 0) {
|
||||||
|
holePunch(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var page = pages[index];
|
||||||
|
|
||||||
|
if (page == INVALID_PAGE) {
|
||||||
|
// Un-holed punch.
|
||||||
|
page = unHolePunch(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ptr = ptrForPage(page);
|
||||||
MemoryUtil.memPutInt(ptr, modelIndex);
|
MemoryUtil.memPutInt(ptr, modelIndex);
|
||||||
MemoryUtil.memPutInt(ptr + 4, i1);
|
MemoryUtil.memPutInt(ptr + 4, validBits);
|
||||||
|
|
||||||
ObjectStorage.this.needsUpload = true;
|
ObjectStorage.this.needsUpload = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a page on the inside of the mapping, maintaining the same virtual mapping size.
|
||||||
|
*
|
||||||
|
* @param index The index of the page to free.
|
||||||
|
*/
|
||||||
|
public void holePunch(int index) {
|
||||||
|
ObjectStorage.this.free(pages[index]);
|
||||||
|
pages[index] = INVALID_PAGE;
|
||||||
|
|
||||||
|
ObjectStorage.this.needsUpload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new page on the inside of the mapping, maintaining the same virtual mapping size.
|
||||||
|
*
|
||||||
|
* @param index The index of the page to allocate.
|
||||||
|
* @return The allocated page.
|
||||||
|
*/
|
||||||
|
private int unHolePunch(int index) {
|
||||||
|
int page = ObjectStorage.this.alloc();
|
||||||
|
pages[index] = page;
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateCount(int newLength) {
|
public void updateCount(int newLength) {
|
||||||
var oldLength = pages.length;
|
var oldLength = pages.length;
|
||||||
if (oldLength > newLength) {
|
if (oldLength > newLength) {
|
||||||
@ -122,8 +164,8 @@ public class ObjectStorage extends AbstractArena {
|
|||||||
return pages.length;
|
return pages.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long page2ByteOffset(int page) {
|
public long page2ByteOffset(int index) {
|
||||||
return ObjectStorage.this.byteOffsetOf(pages[page]);
|
return ObjectStorage.this.byteOffsetOf(pages[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
Loading…
Reference in New Issue
Block a user