89 lines
2.5 KiB
Java
89 lines
2.5 KiB
Java
package com.mojang.blaze3d.resource;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import java.util.ArrayDeque;
|
|
import java.util.Collection;
|
|
import java.util.Deque;
|
|
import java.util.Iterator;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class CrossFrameResourcePool implements GraphicsResourceAllocator, AutoCloseable {
|
|
private final int framesToKeepResource;
|
|
private final Deque<CrossFrameResourcePool.ResourceEntry<?>> pool = new ArrayDeque();
|
|
|
|
public CrossFrameResourcePool(int framesToKeepResource) {
|
|
this.framesToKeepResource = framesToKeepResource;
|
|
}
|
|
|
|
public void endFrame() {
|
|
Iterator<? extends CrossFrameResourcePool.ResourceEntry<?>> iterator = this.pool.iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
CrossFrameResourcePool.ResourceEntry<?> resourceEntry = (CrossFrameResourcePool.ResourceEntry<?>)iterator.next();
|
|
if (resourceEntry.framesToLive-- == 0) {
|
|
resourceEntry.close();
|
|
iterator.remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public <T> T acquire(ResourceDescriptor<T> descriptor) {
|
|
T object = this.acquireWithoutPreparing(descriptor);
|
|
descriptor.prepare(object);
|
|
return object;
|
|
}
|
|
|
|
private <T> T acquireWithoutPreparing(ResourceDescriptor<T> descriptor) {
|
|
Iterator<? extends CrossFrameResourcePool.ResourceEntry<?>> iterator = this.pool.iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
CrossFrameResourcePool.ResourceEntry<?> resourceEntry = (CrossFrameResourcePool.ResourceEntry<?>)iterator.next();
|
|
if (descriptor.canUsePhysicalResource(resourceEntry.descriptor)) {
|
|
iterator.remove();
|
|
return (T)resourceEntry.value;
|
|
}
|
|
}
|
|
|
|
return descriptor.allocate();
|
|
}
|
|
|
|
@Override
|
|
public <T> void release(ResourceDescriptor<T> descriptor, T value) {
|
|
this.pool.addFirst(new CrossFrameResourcePool.ResourceEntry<>(descriptor, value, this.framesToKeepResource));
|
|
}
|
|
|
|
public void clear() {
|
|
this.pool.forEach(CrossFrameResourcePool.ResourceEntry::close);
|
|
this.pool.clear();
|
|
}
|
|
|
|
public void close() {
|
|
this.clear();
|
|
}
|
|
|
|
@VisibleForTesting
|
|
protected Collection<CrossFrameResourcePool.ResourceEntry<?>> entries() {
|
|
return this.pool;
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
@VisibleForTesting
|
|
protected static final class ResourceEntry<T> implements AutoCloseable {
|
|
final ResourceDescriptor<T> descriptor;
|
|
final T value;
|
|
int framesToLive;
|
|
|
|
ResourceEntry(ResourceDescriptor<T> descriptor, T value, int framesToLive) {
|
|
this.descriptor = descriptor;
|
|
this.value = value;
|
|
this.framesToLive = framesToLive;
|
|
}
|
|
|
|
public void close() {
|
|
this.descriptor.free(this.value);
|
|
}
|
|
}
|
|
}
|