minecraft-src/com/mojang/blaze3d/TracyFrameCapture.java
2025-07-04 02:00:41 +03:00

109 lines
3.2 KiB
Java

package com.mojang.blaze3d;
import com.mojang.blaze3d.buffers.BufferType;
import com.mojang.blaze3d.buffers.BufferUsage;
import com.mojang.blaze3d.buffers.GpuBuffer;
import com.mojang.blaze3d.buffers.GpuFence;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.pipeline.TextureTarget;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.jtracy.TracyClient;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class TracyFrameCapture implements AutoCloseable {
private static final int MAX_WIDTH = 320;
private static final int MAX_HEIGHT = 180;
private static final int BYTES_PER_PIXEL = 4;
private int targetWidth;
private int targetHeight;
private int width;
private int height;
private final RenderTarget frameBuffer = new TextureTarget(320, 180, false);
private final GpuBuffer pixelbuffer = new GpuBuffer(BufferType.PIXEL_PACK, BufferUsage.STREAM_READ, 0);
@Nullable
private GpuFence fence;
private int lastCaptureDelay;
private boolean capturedThisFrame;
private void resize(int i, int j) {
float f = (float)i / j;
if (i > 320) {
i = 320;
j = (int)(320.0F / f);
}
if (j > 180) {
i = (int)(180.0F * f);
j = 180;
}
i = i / 4 * 4;
j = j / 4 * 4;
if (this.width != i || this.height != j) {
this.width = i;
this.height = j;
this.frameBuffer.resize(i, j);
this.pixelbuffer.resize(i * j * 4);
if (this.fence != null) {
this.fence.close();
this.fence = null;
}
}
}
public void capture(RenderTarget renderTarget) {
if (this.fence == null && !this.capturedThisFrame) {
this.capturedThisFrame = true;
if (renderTarget.width != this.targetWidth || renderTarget.height != this.targetHeight) {
this.targetWidth = renderTarget.width;
this.targetHeight = renderTarget.height;
this.resize(this.targetWidth, this.targetHeight);
}
GlStateManager._glBindFramebuffer(36009, this.frameBuffer.frameBufferId);
GlStateManager._glBindFramebuffer(36008, renderTarget.frameBufferId);
GlStateManager._glBlitFrameBuffer(0, 0, renderTarget.width, renderTarget.height, 0, 0, this.width, this.height, 16384, 9729);
GlStateManager._glBindFramebuffer(36008, 0);
GlStateManager._glBindFramebuffer(36009, 0);
this.pixelbuffer.bind();
GlStateManager._glBindFramebuffer(36008, this.frameBuffer.frameBufferId);
GlStateManager._readPixels(0, 0, this.width, this.height, 6408, 5121, 0L);
GlStateManager._glBindFramebuffer(36008, 0);
this.fence = new GpuFence();
this.lastCaptureDelay = 0;
}
}
public void upload() {
if (this.fence != null) {
if (this.fence.awaitCompletion(0L)) {
this.fence = null;
try (GpuBuffer.ReadView readView = this.pixelbuffer.read()) {
if (readView != null) {
TracyClient.frameImage(readView.data(), this.width, this.height, this.lastCaptureDelay, true);
}
}
}
}
}
public void endFrame() {
this.lastCaptureDelay++;
this.capturedThisFrame = false;
TracyClient.markFrame();
}
public void close() {
if (this.fence != null) {
this.fence.close();
this.fence = null;
}
this.pixelbuffer.close();
this.frameBuffer.destroyBuffers();
}
}