File size: 5,295 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.mojang.blaze3d.buffers;

import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.jtracy.MemoryPool;
import com.mojang.jtracy.TracyClient;
import java.nio.ByteBuffer;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public class GpuBuffer implements AutoCloseable {
    private static final MemoryPool MEMORY_POOl = TracyClient.createMemoryPool("GPU Buffers");
    private final BufferType type;
    private final BufferUsage usage;
    private boolean closed;
    private boolean initialized = false;
    public final int handle;
    public int size;

    public GpuBuffer(BufferType p_367350_, BufferUsage p_363902_, int p_361832_) {
        this.type = p_367350_;
        this.size = p_361832_;
        this.usage = p_363902_;
        this.handle = GlStateManager._glGenBuffers();
    }

    public GpuBuffer(BufferType p_367048_, BufferUsage p_369969_, ByteBuffer p_364811_) {
        this(p_367048_, p_369969_, p_364811_.remaining());
        this.write(p_364811_, 0);
    }

    public void resize(int p_367249_) {
        if (this.closed) {
            throw new IllegalStateException("Buffer already closed");
        } else {
            if (this.initialized) {
                MEMORY_POOl.free((long)this.handle);
            }

            this.size = p_367249_;
            if (this.usage.writable) {
                this.initialized = false;
            } else {
                this.bind();
                GlStateManager._glBufferData(this.type.id, (long)p_367249_, this.usage.id);
                MEMORY_POOl.malloc((long)this.handle, p_367249_);
                this.initialized = true;
            }
        }
    }

    public void write(ByteBuffer p_363379_, int p_364980_) {
        if (this.closed) {
            throw new IllegalStateException("Buffer already closed");
        } else if (!this.usage.writable) {
            throw new IllegalStateException("Buffer is not writable");
        } else {
            int i = p_363379_.remaining();
            if (i + p_364980_ > this.size) {
                throw new IllegalArgumentException(
                    "Cannot write more data than this buffer can hold (attempting to write "
                        + i
                        + " bytes at offset "
                        + p_364980_
                        + " to "
                        + this.size
                        + " size buffer)"
                );
            } else {
                this.bind();
                if (this.initialized) {
                    GlStateManager._glBufferSubData(this.type.id, p_364980_, p_363379_);
                } else if (p_364980_ == 0 && i == this.size) {
                    GlStateManager._glBufferData(this.type.id, p_363379_, this.usage.id);
                    MEMORY_POOl.malloc((long)this.handle, this.size);
                    this.initialized = true;
                } else {
                    GlStateManager._glBufferData(this.type.id, (long)this.size, this.usage.id);
                    GlStateManager._glBufferSubData(this.type.id, p_364980_, p_363379_);
                    MEMORY_POOl.malloc((long)this.handle, this.size);
                    this.initialized = true;
                }
            }
        }
    }

    @Nullable
    public GpuBuffer.ReadView read() {
        return this.read(0, this.size);
    }

    @Nullable
    public GpuBuffer.ReadView read(int p_361869_, int p_362198_) {
        if (this.closed) {
            throw new IllegalStateException("Buffer already closed");
        } else if (!this.usage.readable) {
            throw new IllegalStateException("Buffer is not readable");
        } else if (p_361869_ + p_362198_ > this.size) {
            throw new IllegalArgumentException(
                "Cannot read more data than this buffer can hold (attempting to read "
                    + p_362198_
                    + " bytes at offset "
                    + p_361869_
                    + " from "
                    + this.size
                    + " size buffer)"
            );
        } else {
            this.bind();
            ByteBuffer bytebuffer = GlStateManager._glMapBufferRange(this.type.id, p_361869_, p_362198_, 1);
            return bytebuffer == null ? null : new GpuBuffer.ReadView(this.type.id, bytebuffer);
        }
    }

    @Override
    public void close() {
        if (!this.closed) {
            this.closed = true;
            GlStateManager._glDeleteBuffers(this.handle);
            if (this.initialized) {
                MEMORY_POOl.free((long)this.handle);
            }
        }
    }

    public void bind() {
        GlStateManager._glBindBuffer(this.type.id, this.handle);
    }

    @OnlyIn(Dist.CLIENT)
    public static class ReadView implements AutoCloseable {
        private final int target;
        private final ByteBuffer data;

        protected ReadView(int p_367113_, ByteBuffer p_362615_) {
            this.target = p_367113_;
            this.data = p_362615_;
        }

        public ByteBuffer data() {
            return this.data;
        }

        @Override
        public void close() {
            GlStateManager._glUnmapBuffer(this.target);
        }
    }
}