File size: 4,058 Bytes
d46f4a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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 javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.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 p_361808_, int p_365044_) {
        float f = (float)p_361808_ / (float)p_365044_;
        if (p_361808_ > 320) {
            p_361808_ = 320;
            p_365044_ = (int)(320.0F / f);
        }

        if (p_365044_ > 180) {
            p_361808_ = (int)(180.0F * f);
            p_365044_ = 180;
        }

        p_361808_ = p_361808_ / 4 * 4;
        p_365044_ = p_365044_ / 4 * 4;
        if (this.width != p_361808_ || this.height != p_365044_) {
            this.width = p_361808_;
            this.height = p_365044_;
            this.frameBuffer.resize(p_361808_, p_365044_);
            this.pixelbuffer.resize(p_361808_ * p_365044_ * 4);
            if (this.fence != null) {
                this.fence.close();
                this.fence = null;
            }
        }
    }

    public void capture(RenderTarget p_367460_) {
        if (this.fence == null && !this.capturedThisFrame) {
            this.capturedThisFrame = true;
            if (p_367460_.width != this.targetWidth || p_367460_.height != this.targetHeight) {
                this.targetWidth = p_367460_.width;
                this.targetHeight = p_367460_.height;
                this.resize(this.targetWidth, this.targetHeight);
            }

            GlStateManager._glBindFramebuffer(36009, this.frameBuffer.frameBufferId);
            GlStateManager._glBindFramebuffer(36008, p_367460_.frameBufferId);
            GlStateManager._glBlitFrameBuffer(0, 0, p_367460_.width, p_367460_.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 gpubuffer$readview = this.pixelbuffer.read()) {
                    if (gpubuffer$readview != null) {
                        TracyClient.frameImage(gpubuffer$readview.data(), this.width, this.height, this.lastCaptureDelay, true);
                    }
                }
            }
        }
    }

    public void endFrame() {
        this.lastCaptureDelay++;
        this.capturedThisFrame = false;
        TracyClient.markFrame();
    }

    @Override
    public void close() {
        if (this.fence != null) {
            this.fence.close();
            this.fence = null;
        }

        this.pixelbuffer.close();
        this.frameBuffer.destroyBuffers();
    }
}