Skip to content

Commit

Permalink
Bookkeeping
Browse files Browse the repository at this point in the history
- Mappings drop pages when they write zero validity bits
- Instancer only updates pages that changed
  • Loading branch information
Jozufozu committed Nov 1, 2024
1 parent 20b3f78 commit fac6316
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public int takeFrom(InstancePage other) {
int otherValid = other.valid.get();

// 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;
}

Expand Down Expand Up @@ -223,15 +223,27 @@ public List<IndirectDraw> draws() {
public void update(int modelIndex, int baseInstance) {
this.baseInstance = baseInstance;

if (this.modelIndex == modelIndex && changedPages.isEmpty()) {
var sameModelIndex = this.modelIndex == modelIndex;
if (sameModelIndex && changedPages.isEmpty()) {
// Nothing to do!
return;
}

this.modelIndex = modelIndex;

var pages = this.pages.get();
mapping.updateCount(pages.length);

for (int i = 0; i < pages.length; i++) {
mapping.updatePage(i, modelIndex, pages[i].valid.get());
if (sameModelIndex) {
// 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());
}
}
}

Expand Down Expand Up @@ -291,46 +303,17 @@ public void uploadInstances(StagingBuffer stagingBuffer, int instanceVbo) {
}

public void parallelUpdate() {
if (true) {
// 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;
}
}
// TODO: Merge pages when they're less than half full.
}

private static boolean isFull(int valid) {
return valid == 0xFFFFFFFF;
}

private static boolean isEmpty(int otherValid) {
return otherValid == 0;
}

@Override
public void delete() {
for (IndirectDraw draw : draws()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_MASK = PAGE_SIZE - 1;

public static final int INVALID_PAGE = -1;

public static final int INITIAL_PAGES_ALLOCATED = 4;
public static final int DESCRIPTOR_SIZE_BYTES = Integer.BYTES * 2;

Expand Down Expand Up @@ -53,8 +55,13 @@ public long byteCapacity() {

@Override
public void free(int i) {
if (i == INVALID_PAGE) {
return;
}
super.free(i);
MemoryUtil.memPutInt(ptrForPage(i), 0);
var ptr = ptrForPage(i);
MemoryUtil.memPutInt(ptr, 0);
MemoryUtil.memPutInt(ptr + 4, 0);
}

@Override
Expand Down Expand Up @@ -98,14 +105,49 @@ public class Mapping {
private static final int[] EMPTY_ALLOCATION = new int[0];
private int[] pages = EMPTY_ALLOCATION;

public void updatePage(int i, int modelIndex, int i1) {
var ptr = ptrForPage(pages[i]);
public void updatePage(int index, int modelIndex, int validBits) {
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 + 4, i1);
MemoryUtil.memPutInt(ptr + 4, validBits);

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) {
var oldLength = pages.length;
if (oldLength > newLength) {
Expand All @@ -122,8 +164,8 @@ public int pageCount() {
return pages.length;
}

public long page2ByteOffset(int page) {
return ObjectStorage.this.byteOffsetOf(pages[page]);
public long page2ByteOffset(int index) {
return ObjectStorage.this.byteOffsetOf(pages[index]);
}

public void delete() {
Expand Down

0 comments on commit fac6316

Please sign in to comment.