UberGpuBuffer.java
com.mojang.blaze3d.vertex.UberGpuBuffer
信息
- 全限定名:com.mojang.blaze3d.vertex.UberGpuBuffer
- 类型:public class
- 包:com.mojang.blaze3d.vertex
- 源码路径:src/main/java/com/mojang/blaze3d/vertex/UberGpuBuffer.java
- 起始行号:L28
- 实现:AutoCloseable
- 职责:
TODO
字段/常量
-
alignSize- 类型:
int - 修饰符:
private final - 源码定位:
L29 - 说明:
TODO
- 类型:
-
stagingBuffer- 类型:
UberGpuBuffer.UberGpuBufferStagingBuffer - 修饰符:
private final - 源码定位:
L30 - 说明:
TODO
- 类型:
-
stagingBufferUsedSize- 类型:
int - 修饰符:
private - 源码定位:
L31 - 说明:
TODO
- 类型:
-
name- 类型:
String - 修饰符:
private final - 源码定位:
L32 - 说明:
TODO
- 类型:
-
nodes- 类型:
List<Pair<TlsfAllocator,UberGpuBuffer.UberGpuBufferHeap>> - 修饰符:
private final - 源码定位:
L33 - 说明:
TODO
- 类型:
-
stagedAllocations- 类型:
Object2ObjectOpenHashMap<T,UberGpuBuffer.StagedAllocationEntry<T>> - 修饰符:
private final - 源码定位:
L34 - 说明:
TODO
- 类型:
-
skippedStagedAllocations- 类型:
ObjectOpenHashSet<T> - 修饰符:
private final - 源码定位:
L35 - 说明:
TODO
- 类型:
-
allocationMap- 类型:
Map<T,TlsfAllocator.Allocation> - 修饰符:
private final - 源码定位:
L36 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
com.mojang.blaze3d.vertex.UberGpuBuffer.StagedAllocationEntry- 类型:
class - 修饰符:
private static - 源码定位:
L190 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.vertex.UberGpuBuffer.UberGpuBufferHeap- 类型:
class - 修饰符:
public static - 源码定位:
L203 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.vertex.UberGpuBuffer.UberGpuBufferStagingBuffer- 类型:
class - 修饰符:
private abstract static - 源码定位:
L213 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.vertex.UberGpuBuffer.UberGpuBufferStagingBuffer.CPUStagingBuffer- 类型:
class - 修饰符:
private static - 源码定位:
L229 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.vertex.UberGpuBuffer.UberGpuBufferStagingBuffer.MappedStagingBuffer- 类型:
class - 修饰符:
private static - 源码定位:
L259 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.vertex.UberGpuBuffer.UploadCallback- 类型:
interface - 修饰符:
public - 源码定位:
L302 - 说明:
TODO
- 类型:
构造器
public UberGpuBuffer(String name, int usage, int heapSize, int alignSize, GpuDevice gpuDevice, int stagingBufferSize, GraphicsWorkarounds workarounds) @ L38
- 构造器名:UberGpuBuffer
- 源码定位:L38
- 修饰符:public
参数:
- name: String
- usage: int
- heapSize: int
- alignSize: int
- gpuDevice: GpuDevice
- stagingBufferSize: int
- workarounds: GraphicsWorkarounds
说明:
TODO
方法
下面的方法块按源码顺序生成。
public boolean addAllocation(T allocationKey, UberGpuBuffer.UploadCallback<T> callback, ByteBuffer buffer) @ L54
- 方法名:addAllocation
- 源码定位:L54
- 返回类型:boolean
- 修饰符:public
参数:
- allocationKey: T
- callback: UberGpuBuffer.UploadCallback
- buffer: ByteBuffer
说明:
TODO
public boolean uploadStagedAllocations(GpuDevice gpuDevice, CommandEncoder encoder) @ L70
- 方法名:uploadStagedAllocations
- 源码定位:L70
- 返回类型:boolean
- 修饰符:public
参数:
- gpuDevice: GpuDevice
- encoder: CommandEncoder
说明:
TODO
public TlsfAllocator.Allocation getAllocation(T allocationKey) @ L141
- 方法名:getAllocation
- 源码定位:L141
- 返回类型:TlsfAllocator.Allocation
- 修饰符:public
参数:
- allocationKey: T
说明:
TODO
public void removeAllocation(T allocationKey) @ L145
- 方法名:removeAllocation
- 源码定位:L145
- 返回类型:void
- 修饰符:public
参数:
- allocationKey: T
说明:
TODO
private void freeAllocation(T allocationKey) @ L150
- 方法名:freeAllocation
- 源码定位:L150
- 返回类型:void
- 修饰符:private
参数:
- allocationKey: T
说明:
TODO
public GpuBuffer getGpuBuffer(TlsfAllocator.Allocation allocation) @ L162
- 方法名:getGpuBuffer
- 源码定位:L162
- 返回类型:GpuBuffer
- 修饰符:public
参数:
- allocation: TlsfAllocator.Allocation
说明:
TODO
public void printStatistics() @ L166
- 方法名:printStatistics
- 源码定位:L166
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void close() @ L175
- 方法名:close
- 源码定位:L175
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class UberGpuBuffer<T> implements AutoCloseable {
private final int alignSize;
private final UberGpuBuffer.UberGpuBufferStagingBuffer stagingBuffer;
private int stagingBufferUsedSize;
private final String name;
private final List<Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap>> nodes;
private final Object2ObjectOpenHashMap<T, UberGpuBuffer.StagedAllocationEntry<T>> stagedAllocations = new Object2ObjectOpenHashMap<>(32);
private final ObjectOpenHashSet<T> skippedStagedAllocations = new ObjectOpenHashSet<>(32);
private final Map<T, TlsfAllocator.Allocation> allocationMap = new HashMap<>(256);
public UberGpuBuffer(String name, int usage, int heapSize, int alignSize, GpuDevice gpuDevice, int stagingBufferSize, GraphicsWorkarounds workarounds) {
if (stagingBufferSize > heapSize) {
throw new IllegalArgumentException("Staging buffer size cannot be bigger than heap size");
} else {
this.name = "UberBuffer " + name;
this.stagingBuffer = UberGpuBuffer.UberGpuBufferStagingBuffer.create(this.name, gpuDevice, stagingBufferSize, workarounds);
this.stagingBufferUsedSize = 0;
this.nodes = new ArrayList<>();
this.alignSize = alignSize;
String initialHeapName = this.name + " 0";
UberGpuBuffer.UberGpuBufferHeap initialHeap = new UberGpuBuffer.UberGpuBufferHeap(heapSize, gpuDevice, usage, initialHeapName);
TlsfAllocator initialTlsfAllocator = new TlsfAllocator(initialHeap);
this.nodes.add(new Pair<>(initialTlsfAllocator, initialHeap));
}
}
public boolean addAllocation(T allocationKey, UberGpuBuffer.@Nullable UploadCallback<T> callback, ByteBuffer buffer) {
int startOffset = this.stagingBufferUsedSize;
ByteBuffer stagingBuffer = this.stagingBuffer.getStagingBuffer();
if (buffer.remaining() > stagingBuffer.capacity()) {
throw new IllegalArgumentException("UberGpuBuffer cannot have any allocations bigger than its staging buffer, increase the staging buffer size!");
} else if (buffer.remaining() > stagingBuffer.capacity() - startOffset) {
return false;
} else {
MemoryUtil.memCopy(buffer, stagingBuffer.position(startOffset));
this.stagingBufferUsedSize = this.stagingBufferUsedSize + buffer.remaining();
UberGpuBuffer.StagedAllocationEntry<T> entry = new UberGpuBuffer.StagedAllocationEntry<>(callback, (long)startOffset, (long)buffer.remaining());
this.stagedAllocations.put(allocationKey, entry);
return true;
}
}
public boolean uploadStagedAllocations(GpuDevice gpuDevice, CommandEncoder encoder) {
for (T key : this.stagedAllocations.keySet()) {
this.freeAllocation(key);
}
boolean newHeapCreatedOrDestroyed = false;
try (Zone ignored = Profiler.get().zone("Upload staged allocations")) {
for (Entry<T, UberGpuBuffer.StagedAllocationEntry<T>> entry : this.stagedAllocations.entrySet()) {
long allocationSize = entry.getValue().size;
if (!this.skippedStagedAllocations.contains(entry.getKey())) {
TlsfAllocator.Allocation allocation = null;
for (Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap> node : this.nodes) {
allocation = node.getFirst().allocate(allocationSize, this.alignSize);
if (allocation != null) {
break;
}
}
if (allocation == null) {
try (Zone ignored2 = Profiler.get().zone("Create new heap")) {
UberGpuBuffer.UberGpuBufferHeap firstHeap = this.nodes.getFirst().getSecond();
long heapSize = firstHeap.gpuBuffer.size();
assert allocationSize <= heapSize;
String heapName = String.format(Locale.ROOT, "%s %d", this.name, this.nodes.size());
UberGpuBuffer.UberGpuBufferHeap newHeap = new UberGpuBuffer.UberGpuBufferHeap(
heapSize, gpuDevice, firstHeap.gpuBuffer.usage(), heapName
);
TlsfAllocator newTlsfAllocator = new TlsfAllocator(newHeap);
this.nodes.add(new Pair<>(newTlsfAllocator, newHeap));
allocation = newTlsfAllocator.allocate(allocationSize, this.alignSize);
newHeapCreatedOrDestroyed = true;
}
}
if (allocation != null) {
TlsfAllocator.Heap allocationHeap = allocation.getHeap();
GpuBuffer allocationDestBuffer = ((UberGpuBuffer.UberGpuBufferHeap)allocationHeap).gpuBuffer;
this.stagingBuffer.copyToHeap(encoder, allocationDestBuffer, allocation.getOffsetFromHeap(), entry.getValue().offset, allocationSize);
this.allocationMap.put(entry.getKey(), allocation);
if (entry.getValue().callback != null) {
entry.getValue().callback.bufferHasBeenUploaded(entry.getKey());
}
}
}
}
this.stagingBuffer.clearFrame(encoder);
this.stagingBufferUsedSize = 0;
this.stagedAllocations.clear();
this.skippedStagedAllocations.clear();
}
Iterator<Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap>> iterator = this.nodes.iterator();
while (iterator.hasNext() && this.nodes.size() > 1) {
Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap> nodex = iterator.next();
if (nodex.getFirst().isCompletelyFree()) {
nodex.getSecond().gpuBuffer.close();
iterator.remove();
newHeapCreatedOrDestroyed = true;
break;
}
}
return newHeapCreatedOrDestroyed;
}
public TlsfAllocator.@Nullable Allocation getAllocation(T allocationKey) {
return this.allocationMap.get(allocationKey);
}
public void removeAllocation(T allocationKey) {
this.skippedStagedAllocations.add(allocationKey);
this.freeAllocation(allocationKey);
}
private void freeAllocation(T allocationKey) {
TlsfAllocator.Allocation allocation = this.allocationMap.remove(allocationKey);
if (allocation != null) {
for (Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap> node : this.nodes) {
if (node.getSecond() == allocation.getHeap()) {
node.getFirst().free(allocation);
break;
}
}
}
}
public GpuBuffer getGpuBuffer(TlsfAllocator.Allocation allocation) {
return ((UberGpuBuffer.UberGpuBufferHeap)allocation.getHeap()).gpuBuffer;
}
@VisibleForDebug
public void printStatistics() {
for (int i = 0; i < this.nodes.size(); i++) {
Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap> node = this.nodes.get(i);
String heapName = String.format(Locale.ROOT, "%s %d", this.name, i);
node.getFirst().printAllocatorStatistics(heapName);
}
}
@Override
public void close() {
this.stagingBuffer.destroyBuffer();
this.stagingBufferUsedSize = 0;
this.stagedAllocations.clear();
this.allocationMap.clear();
for (Pair<TlsfAllocator, UberGpuBuffer.UberGpuBufferHeap> node : this.nodes) {
node.getSecond().gpuBuffer.close();
}
this.nodes.clear();
}
@OnlyIn(Dist.CLIENT)
private static class StagedAllocationEntry<T> {
UberGpuBuffer.@Nullable UploadCallback<T> callback;
long offset;
long size;
private StagedAllocationEntry(UberGpuBuffer.@Nullable UploadCallback<T> callback, long offset, long size) {
this.offset = offset;
this.size = size;
this.callback = callback;
}
}
@OnlyIn(Dist.CLIENT)
public static class UberGpuBufferHeap extends TlsfAllocator.Heap {
GpuBuffer gpuBuffer;
UberGpuBufferHeap(long size, GpuDevice gpuDevice, int usage, String name) {
super(size);
this.gpuBuffer = gpuDevice.createBuffer(() -> name, usage | 8 | 16, size);
}
}
@OnlyIn(Dist.CLIENT)
private abstract static class UberGpuBufferStagingBuffer {
public static UberGpuBuffer.UberGpuBufferStagingBuffer create(String name, GpuDevice gpuDevice, int stagingBufferSize, GraphicsWorkarounds workarounds) {
return (UberGpuBuffer.UberGpuBufferStagingBuffer)(!workarounds.isGlOnDx12()
? new UberGpuBuffer.UberGpuBufferStagingBuffer.CPUStagingBuffer(name, gpuDevice, stagingBufferSize)
: new UberGpuBuffer.UberGpuBufferStagingBuffer.MappedStagingBuffer(name, gpuDevice, stagingBufferSize));
}
abstract ByteBuffer getStagingBuffer();
abstract void copyToHeap(final CommandEncoder encoder, final GpuBuffer heapBuffer, long heapOffset, long stagingBufferOffset, long copySize);
abstract void clearFrame(final CommandEncoder encoder);
abstract void destroyBuffer();
@OnlyIn(Dist.CLIENT)
private static class CPUStagingBuffer extends UberGpuBuffer.UberGpuBufferStagingBuffer {
private final ByteBuffer stagingBuffer;
private CPUStagingBuffer(String name, GpuDevice gpuDevice, int stagingBufferSize) {
this.stagingBuffer = MemoryUtil.memAlloc(stagingBufferSize);
}
@Override
ByteBuffer getStagingBuffer() {
return this.stagingBuffer;
}
@Override
void copyToHeap(CommandEncoder encoder, GpuBuffer heapBuffer, long heapOffset, long stagingBufferOffset, long copySize) {
encoder.writeToBuffer(heapBuffer.slice(heapOffset, copySize), this.stagingBuffer.slice((int)stagingBufferOffset, (int)copySize));
}
@Override
void clearFrame(CommandEncoder encoder) {
this.stagingBuffer.clear();
}
@Override
void destroyBuffer() {
this.stagingBuffer.clear();
MemoryUtil.memFree(this.stagingBuffer);
}
}
@OnlyIn(Dist.CLIENT)
private static class MappedStagingBuffer extends UberGpuBuffer.UberGpuBufferStagingBuffer {
private final MappableRingBuffer mappableRingBuffer;
private GpuBuffer.MappedView currentMappedView;
private GpuBuffer currentGPUBuffer;
private ByteBuffer currentBuffer;
private MappedStagingBuffer(String name, GpuDevice gpuDevice, int stagingBufferSize) {
String stagingBufferName = name + " staging buffer";
this.mappableRingBuffer = new MappableRingBuffer(() -> stagingBufferName, 18, stagingBufferSize / 2);
CommandEncoder encoder = gpuDevice.createCommandEncoder();
this.currentGPUBuffer = this.mappableRingBuffer.currentBuffer();
this.currentMappedView = encoder.mapBuffer(this.currentGPUBuffer, false, true);
this.currentBuffer = this.currentMappedView.data();
}
@Override
ByteBuffer getStagingBuffer() {
return this.currentBuffer;
}
@Override
void copyToHeap(CommandEncoder encoder, GpuBuffer heapBuffer, long heapOffset, long stagingBufferOffset, long copySize) {
encoder.copyToBuffer(this.currentGPUBuffer.slice(stagingBufferOffset, copySize), heapBuffer.slice(heapOffset, copySize));
}
@Override
void clearFrame(CommandEncoder encoder) {
this.currentMappedView.close();
this.mappableRingBuffer.rotate();
this.currentGPUBuffer = this.mappableRingBuffer.currentBuffer();
this.currentMappedView = encoder.mapBuffer(this.currentGPUBuffer, false, true);
this.currentBuffer = this.currentMappedView.data();
}
@Override
void destroyBuffer() {
this.currentMappedView.close();
this.mappableRingBuffer.close();
}
}
}
@OnlyIn(Dist.CLIENT)
public interface UploadCallback<T> {
void bufferHasBeenUploaded(T key);
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/构造调用/返回值 - 关联成员:
TlsfAllocator()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
MappableRingBuffer()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Profiler.get()
- 引用位置: