120 lines
4.8 KiB
Java
120 lines
4.8 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.logging.LogUtils
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.client.renderer;
|
|
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
|
import com.mojang.blaze3d.systems.GpuDevice;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import net.minecraft.client.renderer.MappableRingBuffer;
|
|
import net.minecraft.util.Mth;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class DynamicUniformStorage<T extends DynamicUniform>
|
|
implements AutoCloseable {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private final List<MappableRingBuffer> oldBuffers = new ArrayList<MappableRingBuffer>();
|
|
private final int blockSize;
|
|
private MappableRingBuffer ringBuffer;
|
|
private int nextBlock;
|
|
private int capacity;
|
|
private @Nullable T lastUniform;
|
|
private final String label;
|
|
|
|
public DynamicUniformStorage(String label, int uboSize, int initialCapacity) {
|
|
GpuDevice device = RenderSystem.getDevice();
|
|
this.blockSize = Mth.roundToward(uboSize, device.getUniformOffsetAlignment());
|
|
this.capacity = Mth.smallestEncompassingPowerOfTwo(initialCapacity);
|
|
this.nextBlock = 0;
|
|
this.ringBuffer = new MappableRingBuffer(() -> label + " x" + this.blockSize, 130, this.blockSize * this.capacity);
|
|
this.label = label;
|
|
}
|
|
|
|
public void endFrame() {
|
|
this.nextBlock = 0;
|
|
this.lastUniform = null;
|
|
this.ringBuffer.rotate();
|
|
if (!this.oldBuffers.isEmpty()) {
|
|
for (MappableRingBuffer oldBuffer : this.oldBuffers) {
|
|
oldBuffer.close();
|
|
}
|
|
this.oldBuffers.clear();
|
|
}
|
|
}
|
|
|
|
private void resizeBuffers(int newCapacity) {
|
|
this.capacity = newCapacity;
|
|
this.nextBlock = 0;
|
|
this.lastUniform = null;
|
|
this.oldBuffers.add(this.ringBuffer);
|
|
this.ringBuffer = new MappableRingBuffer(() -> this.label + " x" + this.blockSize, 130, this.blockSize * this.capacity);
|
|
}
|
|
|
|
public GpuBufferSlice writeUniform(T uniform) {
|
|
if (this.lastUniform != null && this.lastUniform.equals(uniform)) {
|
|
return this.ringBuffer.currentBuffer().slice((this.nextBlock - 1) * this.blockSize, this.blockSize);
|
|
}
|
|
if (this.nextBlock >= this.capacity) {
|
|
int newCapacity = this.capacity * 2;
|
|
LOGGER.info("Resizing {}, capacity limit of {} reached during a single frame. New capacity will be {}.", new Object[]{this.label, this.capacity, newCapacity});
|
|
this.resizeBuffers(newCapacity);
|
|
}
|
|
int offset = this.nextBlock * this.blockSize;
|
|
try (GpuBuffer.MappedView view = RenderSystem.getDevice().createCommandEncoder().mapBuffer(this.ringBuffer.currentBuffer().slice(offset, this.blockSize), false, true);){
|
|
uniform.write(view.data());
|
|
}
|
|
++this.nextBlock;
|
|
this.lastUniform = uniform;
|
|
return this.ringBuffer.currentBuffer().slice(offset, this.blockSize);
|
|
}
|
|
|
|
public GpuBufferSlice[] writeUniforms(T[] uniforms) {
|
|
if (uniforms.length == 0) {
|
|
return new GpuBufferSlice[0];
|
|
}
|
|
if (this.nextBlock + uniforms.length > this.capacity) {
|
|
int newCapacity = Mth.smallestEncompassingPowerOfTwo(Math.max(this.capacity + 1, uniforms.length));
|
|
LOGGER.info("Resizing {}, capacity limit of {} reached during a single frame. New capacity will be {}.", new Object[]{this.label, this.capacity, newCapacity});
|
|
this.resizeBuffers(newCapacity);
|
|
}
|
|
int firstOffset = this.nextBlock * this.blockSize;
|
|
GpuBufferSlice[] result = new GpuBufferSlice[uniforms.length];
|
|
try (GpuBuffer.MappedView view = RenderSystem.getDevice().createCommandEncoder().mapBuffer(this.ringBuffer.currentBuffer().slice(firstOffset, uniforms.length * this.blockSize), false, true);){
|
|
ByteBuffer byteBuffer = view.data();
|
|
for (int i = 0; i < uniforms.length; ++i) {
|
|
T uniform = uniforms[i];
|
|
result[i] = this.ringBuffer.currentBuffer().slice(firstOffset + i * this.blockSize, this.blockSize);
|
|
byteBuffer.position(i * this.blockSize);
|
|
uniform.write(byteBuffer);
|
|
}
|
|
}
|
|
this.nextBlock += uniforms.length;
|
|
this.lastUniform = uniforms[uniforms.length - 1];
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
for (MappableRingBuffer oldBuffer : this.oldBuffers) {
|
|
oldBuffer.close();
|
|
}
|
|
this.ringBuffer.close();
|
|
}
|
|
|
|
public static interface DynamicUniform {
|
|
public void write(ByteBuffer var1);
|
|
}
|
|
}
|
|
|