SectionRenderDispatcher.java
net.minecraft.client.renderer.chunk.SectionRenderDispatcher
信息
- 全限定名:net.minecraft.client.renderer.chunk.SectionRenderDispatcher
- 类型:public class
- 包:net.minecraft.client.renderer.chunk
- 源码路径:src/main/java/net/minecraft/client/renderer/chunk/SectionRenderDispatcher.java
- 起始行号:L46
- 职责:
TODO
字段/常量
-
compileQueue- 类型:
CompileTaskDynamicQueue - 修饰符:
private final - 源码定位:
L47 - 说明:
TODO
- 类型:
-
fixedBuffers- 类型:
SectionBufferBuilderPack - 修饰符:
private final - 源码定位:
L48 - 说明:
TODO
- 类型:
-
bufferPool- 类型:
SectionBufferBuilderPool - 修饰符:
private final - 源码定位:
L49 - 说明:
TODO
- 类型:
-
closed- 类型:
boolean - 修饰符:
private volatile - 源码定位:
L50 - 说明:
TODO
- 类型:
-
executor- 类型:
TracingExecutor - 修饰符:
private final - 源码定位:
L51 - 说明:
TODO
- 类型:
-
level- 类型:
ClientLevel - 修饰符:
private - 源码定位:
L52 - 说明:
TODO
- 类型:
-
renderer- 类型:
LevelRenderer - 修饰符:
private final - 源码定位:
L53 - 说明:
TODO
- 类型:
-
cameraPosition- 类型:
AtomicReference<Vec3> - 修饰符:
private final - 源码定位:
L54 - 说明:
TODO
- 类型:
-
sectionCompiler- 类型:
SectionCompiler - 修饰符:
private - 源码定位:
L55 - 说明:
TODO
- 类型:
-
chunkUberBuffers- 类型:
Map<ChunkSectionLayer,SectionRenderDispatcher.SectionUberBuffers> - 修饰符:
private final - 源码定位:
L56 - 说明:
TODO
- 类型:
-
copyLock- 类型:
ReentrantLock - 修饰符:
private final - 源码定位:
L57 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.RenderSection- 类型:
class - 修饰符:
public - 源码定位:
L221 - 说明:
TODO
- 类型:
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.RenderSection.CompileTask- 类型:
class - 修饰符:
public abstract - 源码定位:
L490 - 说明:
TODO
- 类型:
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult- 类型:
enum - 修饰符:
public static - 源码定位:
L518 - 说明:
TODO
- 类型:
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.RenderSection.RebuildTask- 类型:
class - 修饰符:
private - 源码定位:
L525 - 说明:
TODO
- 类型:
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.RenderSection.ResortTransparencyTask- 类型:
class - 修饰符:
private - 源码定位:
L615 - 说明:
TODO
- 类型:
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.RenderSectionBufferSlice- 类型:
record - 修饰符:
public - 源码定位:
L682 - 说明:
TODO
- 类型:
-
net.minecraft.client.renderer.chunk.SectionRenderDispatcher.SectionUberBuffers- 类型:
record - 修饰符:
private - 源码定位:
L686 - 说明:
TODO
- 类型:
构造器
public SectionRenderDispatcher(ClientLevel level, LevelRenderer renderer, TracingExecutor executor, RenderBuffers renderBuffers, SectionCompiler sectionCompiler) @ L59
- 构造器名:SectionRenderDispatcher
- 源码定位:L59
- 修饰符:public
参数:
- level: ClientLevel
- renderer: LevelRenderer
- executor: TracingExecutor
- renderBuffers: RenderBuffers
- sectionCompiler: SectionCompiler
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void setLevel(ClientLevel level, SectionCompiler sectionCompiler) @ L89
- 方法名:setLevel
- 源码定位:L89
- 返回类型:void
- 修饰符:public
参数:
- level: ClientLevel
- sectionCompiler: SectionCompiler
说明:
TODO
private void runTask() @ L94
- 方法名:runTask
- 源码定位:L94
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
public void setCameraPosition(Vec3 cameraPosition) @ L118
- 方法名:setCameraPosition
- 源码定位:L118
- 返回类型:void
- 修饰符:public
参数:
- cameraPosition: Vec3
说明:
TODO
public SectionRenderDispatcher.RenderSectionBufferSlice getRenderSectionSlice(SectionMesh sectionMesh, ChunkSectionLayer layer) @ L122
- 方法名:getRenderSectionSlice
- 源码定位:L122
- 返回类型:SectionRenderDispatcher.RenderSectionBufferSlice
- 修饰符:public
参数:
- sectionMesh: SectionMesh
- layer: ChunkSectionLayer
说明:
TODO
public void lock() @ L143
- 方法名:lock
- 源码定位:L143
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void unlock() @ L147
- 方法名:unlock
- 源码定位:L147
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void uploadGlobalGeomBuffersToGPU() @ L151
- 方法名:uploadGlobalGeomBuffersToGPU
- 源码定位:L151
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void rebuildSectionSync(SectionRenderDispatcher.RenderSection section, RenderRegionCache cache) @ L169
- 方法名:rebuildSectionSync
- 源码定位:L169
- 返回类型:void
- 修饰符:public
参数:
- section: SectionRenderDispatcher.RenderSection
- cache: RenderRegionCache
说明:
TODO
public void schedule(SectionRenderDispatcher.RenderSection.CompileTask task) @ L173
- 方法名:schedule
- 源码定位:L173
- 返回类型:void
- 修饰符:public
参数:
- task: SectionRenderDispatcher.RenderSection.CompileTask
说明:
TODO
public void clearCompileQueue() @ L180
- 方法名:clearCompileQueue
- 源码定位:L180
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isQueueEmpty() @ L184
- 方法名:isQueueEmpty
- 源码定位:L184
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public void dispose() @ L188
- 方法名:dispose
- 源码定位:L188
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public String getStats() @ L205
- 方法名:getStats
- 源码定位:L205
- 返回类型:String
- 修饰符:public
参数:
- 无
说明:
TODO
public int getCompileQueueSize() @ L210
- 方法名:getCompileQueueSize
- 源码定位:L210
- 返回类型:int
- 修饰符:public
参数:
- 无
说明:
TODO
public int getFreeBufferCount() @ L215
- 方法名:getFreeBufferCount
- 源码定位:L215
- 返回类型:int
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class SectionRenderDispatcher {
private final CompileTaskDynamicQueue compileQueue = new CompileTaskDynamicQueue();
private final SectionBufferBuilderPack fixedBuffers;
private final SectionBufferBuilderPool bufferPool;
private volatile boolean closed;
private final TracingExecutor executor;
private ClientLevel level;
private final LevelRenderer renderer;
private final AtomicReference<Vec3> cameraPosition = new AtomicReference<>(Vec3.ZERO);
private SectionCompiler sectionCompiler;
private final Map<ChunkSectionLayer, SectionRenderDispatcher.SectionUberBuffers> chunkUberBuffers;
private final ReentrantLock copyLock = new ReentrantLock();
public SectionRenderDispatcher(
ClientLevel level, LevelRenderer renderer, TracingExecutor executor, RenderBuffers renderBuffers, SectionCompiler sectionCompiler
) {
this.level = level;
this.renderer = renderer;
this.fixedBuffers = renderBuffers.fixedBufferPack();
this.bufferPool = renderBuffers.sectionBufferPool();
this.executor = executor;
this.sectionCompiler = sectionCompiler;
int vertexBufferHeapSize = 134217728;
int indexBufferHeapSize = 33554432;
int vertexStagingBufferSize = 33554432;
int indexStagingBufferSize = 2097152;
GpuDevice gpuDevice = RenderSystem.getDevice();
GraphicsWorkarounds workarounds = GraphicsWorkarounds.get(gpuDevice);
this.chunkUberBuffers = Util.makeEnumMap(
ChunkSectionLayer.class,
layer -> {
VertexFormat vertexFormat = layer.pipeline().getVertexFormat();
UberGpuBuffer<SectionMesh> vertexUberBuffer = new UberGpuBuffer<>(
layer.label(), 32, 134217728, vertexFormat.getVertexSize(), gpuDevice, 33554432, workarounds
);
UberGpuBuffer<SectionMesh> indexUberBuffer = layer == ChunkSectionLayer.TRANSLUCENT
? new UberGpuBuffer<>(layer.label(), 64, 33554432, 8, gpuDevice, 2097152, workarounds)
: null;
return new SectionRenderDispatcher.SectionUberBuffers(vertexUberBuffer, indexUberBuffer);
}
);
}
public void setLevel(ClientLevel level, SectionCompiler sectionCompiler) {
this.level = level;
this.sectionCompiler = sectionCompiler;
}
private void runTask() {
if (!this.closed) {
SectionRenderDispatcher.RenderSection.CompileTask task = this.compileQueue.poll(this.cameraPosition.get());
if (task != null && !task.isCompleted.get() && !task.isCancelled.get()) {
try {
SectionBufferBuilderPack buffer = Objects.requireNonNull(this.bufferPool.acquire());
SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult result = task.doTask(buffer);
task.isCompleted.set(true);
if (result == SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.SUCCESSFUL) {
buffer.clearAll();
} else {
buffer.discardAll();
}
this.bufferPool.release(buffer);
} catch (NullPointerException var4) {
this.compileQueue.add(task);
} catch (Exception var5) {
Minecraft.getInstance().delayCrash(CrashReport.forThrowable(var5, "Batching sections"));
}
}
}
}
public void setCameraPosition(Vec3 cameraPosition) {
this.cameraPosition.set(cameraPosition);
}
public SectionRenderDispatcher.@Nullable RenderSectionBufferSlice getRenderSectionSlice(SectionMesh sectionMesh, ChunkSectionLayer layer) {
SectionRenderDispatcher.SectionUberBuffers uberBuffers = this.chunkUberBuffers.get(layer);
TlsfAllocator.Allocation vertexSlice = uberBuffers.vertexBuffer.getAllocation(sectionMesh);
if (vertexSlice == null) {
return null;
} else {
long vertexBufferOffset = vertexSlice.getOffsetFromHeap();
TlsfAllocator.Allocation indexSlice = uberBuffers.indexBuffer != null ? uberBuffers.indexBuffer.getAllocation(sectionMesh) : null;
long indexBufferOffset = 0L;
GpuBuffer indexBuffer = null;
if (indexSlice != null) {
indexBufferOffset = indexSlice.getOffsetFromHeap();
indexBuffer = uberBuffers.indexBuffer.getGpuBuffer(indexSlice);
}
return new SectionRenderDispatcher.RenderSectionBufferSlice(
uberBuffers.vertexBuffer.getGpuBuffer(vertexSlice), vertexBufferOffset, indexBuffer, indexBufferOffset
);
}
}
public void lock() {
this.copyLock.lock();
}
public void unlock() {
this.copyLock.unlock();
}
public void uploadGlobalGeomBuffersToGPU() {
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
boolean performedBufferResize = false;
for (SectionRenderDispatcher.SectionUberBuffers buffers : this.chunkUberBuffers.values()) {
UberGpuBuffer<SectionMesh> vertexBuffer = buffers.vertexBuffer;
if (performedBufferResize) {
break;
}
performedBufferResize = vertexBuffer.uploadStagedAllocations(RenderSystem.getDevice(), commandEncoder);
UberGpuBuffer<SectionMesh> indexBuffer = buffers.indexBuffer;
if (indexBuffer != null) {
indexBuffer.uploadStagedAllocations(RenderSystem.getDevice(), commandEncoder);
}
}
}
public void rebuildSectionSync(SectionRenderDispatcher.RenderSection section, RenderRegionCache cache) {
section.compileSync(cache);
}
public void schedule(SectionRenderDispatcher.RenderSection.CompileTask task) {
if (!this.closed) {
this.compileQueue.add(task);
this.executor.execute(this::runTask);
}
}
public void clearCompileQueue() {
this.compileQueue.clear();
}
public boolean isQueueEmpty() {
return this.compileQueue.size() == 0;
}
public void dispose() {
this.closed = true;
this.clearCompileQueue();
this.copyLock.lock();
try {
for (SectionRenderDispatcher.SectionUberBuffers buffers : this.chunkUberBuffers.values()) {
buffers.vertexBuffer.close();
if (buffers.indexBuffer != null) {
buffers.indexBuffer.close();
}
}
} finally {
this.copyLock.unlock();
}
}
@VisibleForDebug
public String getStats() {
return String.format(Locale.ROOT, "pC: %03d, aB: %02d", this.compileQueue.size(), this.bufferPool.getFreeBufferCount());
}
@VisibleForDebug
public int getCompileQueueSize() {
return this.compileQueue.size();
}
@VisibleForDebug
public int getFreeBufferCount() {
return this.bufferPool.getFreeBufferCount();
}
@OnlyIn(Dist.CLIENT)
public class RenderSection {
public static final int SIZE = 16;
public final int index;
public final AtomicReference<SectionMesh> sectionMesh;
private SectionRenderDispatcher.RenderSection.@Nullable RebuildTask lastRebuildTask;
private SectionRenderDispatcher.RenderSection.@Nullable ResortTransparencyTask lastResortTransparencyTask;
private AABB bb;
private boolean dirty;
private volatile long sectionNode;
private final BlockPos.MutableBlockPos renderOrigin;
private boolean playerChanged;
private long uploadedTime;
private long fadeDuration;
private boolean wasPreviouslyEmpty;
public RenderSection(int index, long sectionNode) {
Objects.requireNonNull(SectionRenderDispatcher.this);
super();
this.sectionMesh = new AtomicReference<>(CompiledSectionMesh.UNCOMPILED);
this.dirty = true;
this.sectionNode = SectionPos.asLong(-1, -1, -1);
this.renderOrigin = new BlockPos.MutableBlockPos(-1, -1, -1);
this.index = index;
this.setSectionNode(sectionNode);
}
public float getVisibility(long now) {
long elapsed = now - this.uploadedTime;
return elapsed >= this.fadeDuration ? 1.0F : (float)elapsed / (float)this.fadeDuration;
}
public void setFadeDuration(long fadeDuration) {
this.fadeDuration = fadeDuration;
}
public void setWasPreviouslyEmpty(boolean wasPreviouslyEmpty) {
this.wasPreviouslyEmpty = wasPreviouslyEmpty;
}
public boolean wasPreviouslyEmpty() {
return this.wasPreviouslyEmpty;
}
private boolean doesChunkExistAt(long sectionNode) {
ChunkAccess chunk = SectionRenderDispatcher.this.level.getChunk(SectionPos.x(sectionNode), SectionPos.z(sectionNode), ChunkStatus.FULL, false);
return chunk != null && SectionRenderDispatcher.this.level.getLightEngine().lightOnInColumn(SectionPos.getZeroNode(sectionNode));
}
public boolean hasAllNeighbors() {
return this.doesChunkExistAt(SectionPos.offset(this.sectionNode, Direction.WEST))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, Direction.NORTH))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, Direction.EAST))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, Direction.SOUTH))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, -1, 0, -1))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, -1, 0, 1))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, 1, 0, -1))
&& this.doesChunkExistAt(SectionPos.offset(this.sectionNode, 1, 0, 1));
}
public AABB getBoundingBox() {
return this.bb;
}
public void setSectionNode(long sectionNode) {
this.reset();
this.sectionNode = sectionNode;
int x = SectionPos.sectionToBlockCoord(SectionPos.x(sectionNode));
int y = SectionPos.sectionToBlockCoord(SectionPos.y(sectionNode));
int z = SectionPos.sectionToBlockCoord(SectionPos.z(sectionNode));
this.renderOrigin.set(x, y, z);
this.bb = new AABB(x, y, z, x + 16, y + 16, z + 16);
}
public SectionMesh getSectionMesh() {
return this.sectionMesh.get();
}
public void reset() {
this.cancelTasks();
SectionMesh mesh = this.sectionMesh.getAndSet(CompiledSectionMesh.UNCOMPILED);
SectionRenderDispatcher.this.copyLock.lock();
try {
this.releaseSectionMesh(mesh);
} finally {
SectionRenderDispatcher.this.copyLock.unlock();
}
this.dirty = true;
this.uploadedTime = 0L;
this.wasPreviouslyEmpty = false;
}
public BlockPos getRenderOrigin() {
return this.renderOrigin;
}
public long getSectionNode() {
return this.sectionNode;
}
public void setDirty(boolean fromPlayer) {
boolean wasDirty = this.dirty;
this.dirty = true;
this.playerChanged = fromPlayer | (wasDirty && this.playerChanged);
}
public void setNotDirty() {
this.dirty = false;
this.playerChanged = false;
}
public boolean isDirty() {
return this.dirty;
}
public boolean isDirtyFromPlayer() {
return this.dirty && this.playerChanged;
}
public long getNeighborSectionNode(Direction direction) {
return SectionPos.offset(this.sectionNode, direction);
}
public void resortTransparency(SectionRenderDispatcher dispatcher) {
if (this.getSectionMesh() instanceof CompiledSectionMesh mesh) {
this.lastResortTransparencyTask = new SectionRenderDispatcher.RenderSection.ResortTransparencyTask(mesh);
dispatcher.schedule(this.lastResortTransparencyTask);
}
}
public boolean hasTranslucentGeometry() {
return this.getSectionMesh().hasTranslucentGeometry();
}
public boolean transparencyResortingScheduled() {
return this.lastResortTransparencyTask != null && !this.lastResortTransparencyTask.isCompleted.get();
}
protected void cancelTasks() {
if (this.lastRebuildTask != null) {
this.lastRebuildTask.cancel();
this.lastRebuildTask = null;
}
if (this.lastResortTransparencyTask != null) {
this.lastResortTransparencyTask.cancel();
this.lastResortTransparencyTask = null;
}
}
public SectionRenderDispatcher.RenderSection.CompileTask createCompileTask(RenderRegionCache cache) {
this.cancelTasks();
RenderSectionRegion region = cache.createRegion(SectionRenderDispatcher.this.level, this.sectionNode);
boolean isRecompile = this.sectionMesh.get() != CompiledSectionMesh.UNCOMPILED;
this.lastRebuildTask = new SectionRenderDispatcher.RenderSection.RebuildTask(region, isRecompile);
return this.lastRebuildTask;
}
public void rebuildSectionAsync(RenderRegionCache cache) {
SectionRenderDispatcher.RenderSection.CompileTask task = this.createCompileTask(cache);
SectionRenderDispatcher.this.schedule(task);
}
public void compileSync(RenderRegionCache cache) {
SectionRenderDispatcher.RenderSection.CompileTask task = this.createCompileTask(cache);
task.doTask(SectionRenderDispatcher.this.fixedBuffers);
}
private SectionMesh setSectionMesh(SectionMesh sectionMesh) {
SectionMesh oldMesh = this.sectionMesh.getAndSet(sectionMesh);
SectionRenderDispatcher.this.renderer.addRecentlyCompiledSection(this);
if (this.uploadedTime == 0L) {
this.uploadedTime = Util.getMillis();
}
return oldMesh;
}
private void releaseSectionMesh(SectionMesh oldMesh) {
oldMesh.close();
for (SectionRenderDispatcher.SectionUberBuffers buffers : SectionRenderDispatcher.this.chunkUberBuffers.values()) {
UberGpuBuffer<SectionMesh> vertexBuffer = buffers.vertexBuffer;
vertexBuffer.removeAllocation(oldMesh);
UberGpuBuffer<SectionMesh> indexBuffer = buffers.indexBuffer;
if (indexBuffer != null) {
indexBuffer.removeAllocation(oldMesh);
}
}
}
private VertexSorting createVertexSorting(SectionPos sectionPos, Vec3 cameraPos) {
return VertexSorting.byDistance(
(float)(cameraPos.x - sectionPos.minBlockX()), (float)(cameraPos.y - sectionPos.minBlockY()), (float)(cameraPos.z - sectionPos.minBlockZ())
);
}
private void checkSectionMesh(CompiledSectionMesh compiledSectionMesh) {
boolean allBuffersUpdated = true;
for (ChunkSectionLayer layer : ChunkSectionLayer.values()) {
SectionMesh.SectionDraw draw = compiledSectionMesh.getSectionDraw(layer);
if (draw != null) {
allBuffersUpdated &= compiledSectionMesh.isIndexBufferUploaded(layer);
allBuffersUpdated &= compiledSectionMesh.isVertexBufferUploaded(layer);
}
}
if (allBuffersUpdated && this.sectionMesh.get() != compiledSectionMesh) {
SectionMesh oldMesh = this.setSectionMesh(compiledSectionMesh);
this.releaseSectionMesh(oldMesh);
}
}
void vertexBufferUploadCallback(SectionMesh sectionMesh, ChunkSectionLayer layer) {
if (sectionMesh instanceof CompiledSectionMesh compiledSectionMesh) {
compiledSectionMesh.setVertexBufferUploaded(layer);
this.checkSectionMesh(compiledSectionMesh);
}
}
void indexBufferUploadCallback(SectionMesh sectionMesh, ChunkSectionLayer layer, boolean sortedIndexBuffer) {
if (sectionMesh instanceof CompiledSectionMesh compiledSectionMesh) {
compiledSectionMesh.setIndexBufferUploaded(layer);
if (!sortedIndexBuffer) {
this.checkSectionMesh(compiledSectionMesh);
}
}
}
private boolean addSectionBuffersToUberBuffer(
ChunkSectionLayer layer, CompiledSectionMesh key, @Nullable ByteBuffer vertexBuffer, @Nullable ByteBuffer indexBuffer
) {
boolean success = true;
SectionRenderDispatcher.this.copyLock.lock();
try {
SectionMesh.SectionDraw draw = key.getSectionDraw(layer);
if (draw != null) {
SectionRenderDispatcher.SectionUberBuffers sectionBuffers = SectionRenderDispatcher.this.chunkUberBuffers.get(layer);
assert sectionBuffers != null;
if (vertexBuffer != null) {
UberGpuBuffer.UploadCallback<SectionMesh> callback = mesh -> this.vertexBufferUploadCallback(mesh, layer);
success &= sectionBuffers.vertexBuffer.addAllocation(key, callback, vertexBuffer);
}
if (indexBuffer != null) {
boolean sortedIndexBuffer = vertexBuffer == null;
UberGpuBuffer.UploadCallback<SectionMesh> callback = mesh -> this.indexBufferUploadCallback(mesh, layer, sortedIndexBuffer);
success &= sectionBuffers.indexBuffer.addAllocation(key, callback, indexBuffer);
} else {
key.setIndexBufferUploaded(layer);
}
}
if (!success && RenderSystem.isOnRenderThread()) {
SectionRenderDispatcher.this.uploadGlobalGeomBuffersToGPU();
}
} finally {
SectionRenderDispatcher.this.copyLock.unlock();
}
return success;
}
@OnlyIn(Dist.CLIENT)
public abstract class CompileTask {
protected final AtomicBoolean isCancelled;
protected final AtomicBoolean isCompleted;
protected final boolean isRecompile;
public CompileTask(boolean isRecompile) {
Objects.requireNonNull(RenderSection.this);
super();
this.isCancelled = new AtomicBoolean(false);
this.isCompleted = new AtomicBoolean(false);
this.isRecompile = isRecompile;
}
public abstract SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult doTask(final SectionBufferBuilderPack buffers);
public abstract void cancel();
protected abstract String name();
public boolean isRecompile() {
return this.isRecompile;
}
public BlockPos getRenderOrigin() {
return RenderSection.this.renderOrigin;
}
@OnlyIn(Dist.CLIENT)
public static enum SectionTaskResult {
SUCCESSFUL,
CANCELLED;
}
}
@OnlyIn(Dist.CLIENT)
private class RebuildTask extends SectionRenderDispatcher.RenderSection.CompileTask {
protected final RenderSectionRegion region;
public RebuildTask(RenderSectionRegion region, boolean isRecompile) {
Objects.requireNonNull(RenderSection.this);
super(isRecompile);
this.region = region;
}
@Override
protected String name() {
return "rend_chk_rebuild";
}
@Override
public SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult doTask(SectionBufferBuilderPack buffers) {
if (this.isCancelled.get()) {
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
} else {
long sectionNode = RenderSection.this.sectionNode;
SectionPos sectionPos = SectionPos.of(sectionNode);
if (this.isCancelled.get()) {
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
} else {
Vec3 cameraPos = SectionRenderDispatcher.this.cameraPosition.get();
SectionCompiler.Results results;
try (Zone ignored = Profiler.get().zone("Compile Section")) {
results = SectionRenderDispatcher.this.sectionCompiler
.compile(sectionPos, this.region, RenderSection.this.createVertexSorting(sectionPos, cameraPos), buffers);
}
TranslucencyPointOfView translucencyPointOfView = TranslucencyPointOfView.of(cameraPos, sectionNode);
CompiledSectionMesh compiledSectionMesh = new CompiledSectionMesh(translucencyPointOfView, results);
if (results.renderedLayers.isEmpty()) {
SectionMesh oldMesh = RenderSection.this.setSectionMesh(compiledSectionMesh);
SectionRenderDispatcher.this.copyLock.lock();
try {
RenderSection.this.releaseSectionMesh(oldMesh);
} finally {
SectionRenderDispatcher.this.copyLock.unlock();
}
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.SUCCESSFUL;
} else {
for (Entry<ChunkSectionLayer, MeshData> entry : results.renderedLayers.entrySet()) {
MeshData meshData = entry.getValue();
boolean success = false;
while (!success) {
if (this.isCancelled.get()) {
results.release();
SectionRenderDispatcher.this.copyLock.lock();
try {
RenderSection.this.releaseSectionMesh(compiledSectionMesh);
} finally {
SectionRenderDispatcher.this.copyLock.unlock();
}
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
}
success = RenderSection.this.addSectionBuffersToUberBuffer(
entry.getKey(), compiledSectionMesh, meshData.vertexBuffer(), meshData.indexBuffer()
);
if (!success && !RenderSystem.isOnRenderThread()) {
Thread.onSpinWait();
}
}
meshData.close();
}
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.SUCCESSFUL;
}
}
}
}
@Override
public void cancel() {
if (this.isCancelled.compareAndSet(false, true)) {
RenderSection.this.setDirty(false);
}
}
}
@OnlyIn(Dist.CLIENT)
private class ResortTransparencyTask extends SectionRenderDispatcher.RenderSection.CompileTask {
private final CompiledSectionMesh compiledSectionMesh;
public ResortTransparencyTask(CompiledSectionMesh compiledSectionMesh) {
Objects.requireNonNull(RenderSection.this);
super(true);
this.compiledSectionMesh = compiledSectionMesh;
}
@Override
protected String name() {
return "rend_chk_sort";
}
@Override
public SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult doTask(SectionBufferBuilderPack buffers) {
if (this.isCancelled.get()) {
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
} else {
MeshData.SortState state = this.compiledSectionMesh.getTransparencyState();
if (state != null && !this.compiledSectionMesh.isEmpty(ChunkSectionLayer.TRANSLUCENT)) {
Vec3 cameraPos = SectionRenderDispatcher.this.cameraPosition.get();
long sectionNode = RenderSection.this.sectionNode;
VertexSorting vertexSorting = RenderSection.this.createVertexSorting(SectionPos.of(sectionNode), cameraPos);
TranslucencyPointOfView translucencyPointOfView = TranslucencyPointOfView.of(cameraPos, sectionNode);
if (!this.compiledSectionMesh.isDifferentPointOfView(translucencyPointOfView) && !translucencyPointOfView.isAxisAligned()) {
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
} else {
ByteBufferBuilder.Result indexBuffer = state.buildSortedIndexBuffer(buffers.buffer(ChunkSectionLayer.TRANSLUCENT), vertexSorting);
if (indexBuffer == null) {
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
} else {
boolean success = false;
while (!success) {
if (this.isCancelled.get()) {
indexBuffer.close();
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
}
success = RenderSection.this.addSectionBuffersToUberBuffer(
ChunkSectionLayer.TRANSLUCENT, this.compiledSectionMesh, null, indexBuffer.byteBuffer()
);
if (!success && !RenderSystem.isOnRenderThread()) {
Thread.onSpinWait();
}
}
indexBuffer.close();
this.compiledSectionMesh.setTranslucencyPointOfView(translucencyPointOfView);
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.SUCCESSFUL;
}
}
} else {
return SectionRenderDispatcher.RenderSection.CompileTask.SectionTaskResult.CANCELLED;
}
}
}
@Override
public void cancel() {
this.isCancelled.set(true);
}
}
}
@OnlyIn(Dist.CLIENT)
public record RenderSectionBufferSlice(GpuBuffer vertexBuffer, long vertexBufferOffset, @Nullable GpuBuffer indexBuffer, long indexBufferOffset) {
}
@OnlyIn(Dist.CLIENT)
private record SectionUberBuffers(UberGpuBuffer<SectionMesh> vertexBuffer, @Nullable UberGpuBuffer<SectionMesh> indexBuffer) {
}
}引用的其他类
-
- 引用位置:
方法调用 - 关联成员:
GraphicsWorkarounds.get()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
RenderSystem.getDevice(), RenderSystem.isOnRenderThread()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
VertexSorting.byDistance()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
CrashReport.forThrowable()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Minecraft.getInstance()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
参数/字段/方法调用 - 关联成员:
ChunkSectionLayer.values()
- 引用位置:
-
- 引用位置:
字段/构造调用 - 关联成员:
CompileTaskDynamicQueue()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
CompiledSectionMesh()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TranslucencyPointOfView.of()
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
BlockPos.MutableBlockPos(), MutableBlockPos()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SectionPos.asLong(), SectionPos.getZeroNode(), SectionPos.of(), SectionPos.offset(), SectionPos.sectionToBlockCoord(), SectionPos.x(), SectionPos.y(), SectionPos.z()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.getMillis(), Util.makeEnumMap()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Profiler.get()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
AABB()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置: