xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/BufferMtl.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // BufferMtl.h:
7*8975f5c5SAndroid Build Coastguard Worker //    Defines the class interface for BufferMtl, implementing BufferImpl.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #ifndef LIBANGLE_RENDERER_METAL_BUFFERMTL_H_
11*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_RENDERER_METAL_BUFFERMTL_H_
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #import <Metal/Metal.h>
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker #include <optional>
16*8975f5c5SAndroid Build Coastguard Worker #include <utility>
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Observer.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/BufferImpl.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/Format.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_buffer_pool.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_resources.h"
25*8975f5c5SAndroid Build Coastguard Worker 
26*8975f5c5SAndroid Build Coastguard Worker namespace rx
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker 
29*8975f5c5SAndroid Build Coastguard Worker struct DrawCommandRange
30*8975f5c5SAndroid Build Coastguard Worker {
31*8975f5c5SAndroid Build Coastguard Worker     uint32_t count;
32*8975f5c5SAndroid Build Coastguard Worker     size_t offset;
33*8975f5c5SAndroid Build Coastguard Worker };
34*8975f5c5SAndroid Build Coastguard Worker 
35*8975f5c5SAndroid Build Coastguard Worker // Inclusive range of consecutive primitive restart value indexes.
36*8975f5c5SAndroid Build Coastguard Worker struct IndexRange
37*8975f5c5SAndroid Build Coastguard Worker {
IndexRangeIndexRange38*8975f5c5SAndroid Build Coastguard Worker     IndexRange(size_t begin, size_t end) : restartBegin(begin), restartEnd(end) {}
39*8975f5c5SAndroid Build Coastguard Worker     size_t restartBegin;
40*8975f5c5SAndroid Build Coastguard Worker     size_t restartEnd;
41*8975f5c5SAndroid Build Coastguard Worker };
42*8975f5c5SAndroid Build Coastguard Worker // Conversion buffers hold translated index and vertex data.
43*8975f5c5SAndroid Build Coastguard Worker struct ConversionBufferMtl
44*8975f5c5SAndroid Build Coastguard Worker {
45*8975f5c5SAndroid Build Coastguard Worker     ConversionBufferMtl(ContextMtl *context, size_t initialSize, size_t alignment);
46*8975f5c5SAndroid Build Coastguard Worker     ~ConversionBufferMtl();
47*8975f5c5SAndroid Build Coastguard Worker 
48*8975f5c5SAndroid Build Coastguard Worker     // One state value determines if we need to re-stream vertex data.
49*8975f5c5SAndroid Build Coastguard Worker     bool dirty;
50*8975f5c5SAndroid Build Coastguard Worker 
51*8975f5c5SAndroid Build Coastguard Worker     // The conversion is stored in a dynamic buffer.
52*8975f5c5SAndroid Build Coastguard Worker     mtl::BufferPool data;
53*8975f5c5SAndroid Build Coastguard Worker     // These properties are to be filled by user of this buffer conversion
54*8975f5c5SAndroid Build Coastguard Worker     mtl::BufferRef convertedBuffer;
55*8975f5c5SAndroid Build Coastguard Worker     size_t convertedOffset;
56*8975f5c5SAndroid Build Coastguard Worker };
57*8975f5c5SAndroid Build Coastguard Worker 
58*8975f5c5SAndroid Build Coastguard Worker struct VertexConversionBufferMtl : public ConversionBufferMtl
59*8975f5c5SAndroid Build Coastguard Worker {
60*8975f5c5SAndroid Build Coastguard Worker     VertexConversionBufferMtl(ContextMtl *context,
61*8975f5c5SAndroid Build Coastguard Worker                               angle::FormatID formatIDIn,
62*8975f5c5SAndroid Build Coastguard Worker                               GLuint strideIn,
63*8975f5c5SAndroid Build Coastguard Worker                               size_t offsetIn);
64*8975f5c5SAndroid Build Coastguard Worker 
65*8975f5c5SAndroid Build Coastguard Worker     // The conversion is identified by the triple of {format, stride, offset}.
66*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID formatID;
67*8975f5c5SAndroid Build Coastguard Worker     GLuint stride;
68*8975f5c5SAndroid Build Coastguard Worker     size_t offset;
69*8975f5c5SAndroid Build Coastguard Worker };
70*8975f5c5SAndroid Build Coastguard Worker 
71*8975f5c5SAndroid Build Coastguard Worker struct IndexConversionBufferMtl : public ConversionBufferMtl
72*8975f5c5SAndroid Build Coastguard Worker {
73*8975f5c5SAndroid Build Coastguard Worker     IndexConversionBufferMtl(ContextMtl *context,
74*8975f5c5SAndroid Build Coastguard Worker                              gl::DrawElementsType elemType,
75*8975f5c5SAndroid Build Coastguard Worker                              bool primitiveRestartEnabled,
76*8975f5c5SAndroid Build Coastguard Worker                              size_t offsetIn);
77*8975f5c5SAndroid Build Coastguard Worker     const gl::DrawElementsType elemType;
78*8975f5c5SAndroid Build Coastguard Worker     const size_t offset;
79*8975f5c5SAndroid Build Coastguard Worker     bool primitiveRestartEnabled;
80*8975f5c5SAndroid Build Coastguard Worker     IndexRange getRangeForConvertedBuffer(size_t count);
81*8975f5c5SAndroid Build Coastguard Worker };
82*8975f5c5SAndroid Build Coastguard Worker 
83*8975f5c5SAndroid Build Coastguard Worker struct UniformConversionBufferMtl : public ConversionBufferMtl
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker     UniformConversionBufferMtl(ContextMtl *context,
86*8975f5c5SAndroid Build Coastguard Worker                                std::pair<size_t, size_t> offsetIn,
87*8975f5c5SAndroid Build Coastguard Worker                                size_t blockSize);
88*8975f5c5SAndroid Build Coastguard Worker 
initialSrcOffsetUniformConversionBufferMtl89*8975f5c5SAndroid Build Coastguard Worker     size_t initialSrcOffset() { return offset.second; }
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker     const size_t uniformBufferBlockSize;
92*8975f5c5SAndroid Build Coastguard Worker     const std::pair<size_t, size_t> offset;
93*8975f5c5SAndroid Build Coastguard Worker };
94*8975f5c5SAndroid Build Coastguard Worker 
95*8975f5c5SAndroid Build Coastguard Worker class BufferHolderMtl
96*8975f5c5SAndroid Build Coastguard Worker {
97*8975f5c5SAndroid Build Coastguard Worker   public:
98*8975f5c5SAndroid Build Coastguard Worker     virtual ~BufferHolderMtl() = default;
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker     // Due to the complication of synchronizing accesses between CPU and GPU,
101*8975f5c5SAndroid Build Coastguard Worker     // a mtl::Buffer might be under used by GPU but CPU wants to modify its content through
102*8975f5c5SAndroid Build Coastguard Worker     // map() method, this could lead to GPU stalling. The more efficient method is maintain
103*8975f5c5SAndroid Build Coastguard Worker     // a queue of mtl::Buffer and only let CPU modifies a free mtl::Buffer.
104*8975f5c5SAndroid Build Coastguard Worker     // So, in order to let GPU use the most recent modified content, one must call this method
105*8975f5c5SAndroid Build Coastguard Worker     // right before the draw call to retrieved the most up-to-date mtl::Buffer.
getCurrentBuffer()106*8975f5c5SAndroid Build Coastguard Worker     mtl::BufferRef getCurrentBuffer() const { return mIsWeak ? mBufferWeakRef.lock() : mBuffer; }
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker   protected:
109*8975f5c5SAndroid Build Coastguard Worker     mtl::BufferRef mBuffer;
110*8975f5c5SAndroid Build Coastguard Worker     mtl::BufferWeakRef mBufferWeakRef;
111*8975f5c5SAndroid Build Coastguard Worker     bool mIsWeak = false;
112*8975f5c5SAndroid Build Coastguard Worker };
113*8975f5c5SAndroid Build Coastguard Worker 
114*8975f5c5SAndroid Build Coastguard Worker class BufferMtl : public BufferImpl, public BufferHolderMtl
115*8975f5c5SAndroid Build Coastguard Worker {
116*8975f5c5SAndroid Build Coastguard Worker   public:
117*8975f5c5SAndroid Build Coastguard Worker     BufferMtl(const gl::BufferState &state);
118*8975f5c5SAndroid Build Coastguard Worker     ~BufferMtl() override;
119*8975f5c5SAndroid Build Coastguard Worker     void destroy(const gl::Context *context) override;
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker     angle::Result setData(const gl::Context *context,
122*8975f5c5SAndroid Build Coastguard Worker                           gl::BufferBinding target,
123*8975f5c5SAndroid Build Coastguard Worker                           const void *data,
124*8975f5c5SAndroid Build Coastguard Worker                           size_t size,
125*8975f5c5SAndroid Build Coastguard Worker                           gl::BufferUsage usage) override;
126*8975f5c5SAndroid Build Coastguard Worker     angle::Result setSubData(const gl::Context *context,
127*8975f5c5SAndroid Build Coastguard Worker                              gl::BufferBinding target,
128*8975f5c5SAndroid Build Coastguard Worker                              const void *data,
129*8975f5c5SAndroid Build Coastguard Worker                              size_t size,
130*8975f5c5SAndroid Build Coastguard Worker                              size_t offset) override;
131*8975f5c5SAndroid Build Coastguard Worker     angle::Result copySubData(const gl::Context *context,
132*8975f5c5SAndroid Build Coastguard Worker                               BufferImpl *source,
133*8975f5c5SAndroid Build Coastguard Worker                               GLintptr sourceOffset,
134*8975f5c5SAndroid Build Coastguard Worker                               GLintptr destOffset,
135*8975f5c5SAndroid Build Coastguard Worker                               GLsizeiptr size) override;
136*8975f5c5SAndroid Build Coastguard Worker     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
137*8975f5c5SAndroid Build Coastguard Worker     angle::Result mapRange(const gl::Context *context,
138*8975f5c5SAndroid Build Coastguard Worker                            size_t offset,
139*8975f5c5SAndroid Build Coastguard Worker                            size_t length,
140*8975f5c5SAndroid Build Coastguard Worker                            GLbitfield access,
141*8975f5c5SAndroid Build Coastguard Worker                            void **mapPtr) override;
142*8975f5c5SAndroid Build Coastguard Worker     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
143*8975f5c5SAndroid Build Coastguard Worker 
144*8975f5c5SAndroid Build Coastguard Worker     angle::Result getIndexRange(const gl::Context *context,
145*8975f5c5SAndroid Build Coastguard Worker                                 gl::DrawElementsType type,
146*8975f5c5SAndroid Build Coastguard Worker                                 size_t offset,
147*8975f5c5SAndroid Build Coastguard Worker                                 size_t count,
148*8975f5c5SAndroid Build Coastguard Worker                                 bool primitiveRestartEnabled,
149*8975f5c5SAndroid Build Coastguard Worker                                 gl::IndexRange *outRange) override;
150*8975f5c5SAndroid Build Coastguard Worker 
151*8975f5c5SAndroid Build Coastguard Worker     void onDataChanged() override;
152*8975f5c5SAndroid Build Coastguard Worker 
153*8975f5c5SAndroid Build Coastguard Worker     angle::Result getFirstLastIndices(ContextMtl *contextMtl,
154*8975f5c5SAndroid Build Coastguard Worker                                       gl::DrawElementsType type,
155*8975f5c5SAndroid Build Coastguard Worker                                       size_t offset,
156*8975f5c5SAndroid Build Coastguard Worker                                       size_t count,
157*8975f5c5SAndroid Build Coastguard Worker                                       std::pair<uint32_t, uint32_t> *outIndices);
158*8975f5c5SAndroid Build Coastguard Worker 
159*8975f5c5SAndroid Build Coastguard Worker     const uint8_t *getBufferDataReadOnly(ContextMtl *contextMtl);
160*8975f5c5SAndroid Build Coastguard Worker     bool isSafeToReadFromBufferViaBlit(ContextMtl *contextMtl);
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker     ConversionBufferMtl *getVertexConversionBuffer(ContextMtl *context,
163*8975f5c5SAndroid Build Coastguard Worker                                                    angle::FormatID formatID,
164*8975f5c5SAndroid Build Coastguard Worker                                                    GLuint stride,
165*8975f5c5SAndroid Build Coastguard Worker                                                    size_t offset);
166*8975f5c5SAndroid Build Coastguard Worker 
167*8975f5c5SAndroid Build Coastguard Worker     IndexConversionBufferMtl *getIndexConversionBuffer(ContextMtl *context,
168*8975f5c5SAndroid Build Coastguard Worker                                                        gl::DrawElementsType elemType,
169*8975f5c5SAndroid Build Coastguard Worker                                                        bool primitiveRestartEnabled,
170*8975f5c5SAndroid Build Coastguard Worker                                                        size_t offset);
171*8975f5c5SAndroid Build Coastguard Worker 
172*8975f5c5SAndroid Build Coastguard Worker     ConversionBufferMtl *getUniformConversionBuffer(ContextMtl *context,
173*8975f5c5SAndroid Build Coastguard Worker                                                     std::pair<size_t, size_t> offset,
174*8975f5c5SAndroid Build Coastguard Worker                                                     size_t blockSize);
175*8975f5c5SAndroid Build Coastguard Worker 
size()176*8975f5c5SAndroid Build Coastguard Worker     size_t size() const { return static_cast<size_t>(mState.getSize()); }
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker     const std::vector<IndexRange> &getRestartIndices(ContextMtl *ctx,
179*8975f5c5SAndroid Build Coastguard Worker                                                      gl::DrawElementsType indexType);
180*8975f5c5SAndroid Build Coastguard Worker 
181*8975f5c5SAndroid Build Coastguard Worker     static const std::vector<IndexRange> getRestartIndicesFromClientData(
182*8975f5c5SAndroid Build Coastguard Worker         ContextMtl *ctx,
183*8975f5c5SAndroid Build Coastguard Worker         gl::DrawElementsType indexType,
184*8975f5c5SAndroid Build Coastguard Worker         const mtl::BufferRef clientBuffer);
185*8975f5c5SAndroid Build Coastguard Worker 
186*8975f5c5SAndroid Build Coastguard Worker   private:
187*8975f5c5SAndroid Build Coastguard Worker     angle::Result allocateNewMetalBuffer(ContextMtl *contextMtl,
188*8975f5c5SAndroid Build Coastguard Worker                                          MTLStorageMode storageMode,
189*8975f5c5SAndroid Build Coastguard Worker                                          size_t size,
190*8975f5c5SAndroid Build Coastguard Worker                                          bool returnOldBufferImmediately);
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker     angle::Result setDataImpl(const gl::Context *context,
193*8975f5c5SAndroid Build Coastguard Worker                               gl::BufferBinding target,
194*8975f5c5SAndroid Build Coastguard Worker                               const void *data,
195*8975f5c5SAndroid Build Coastguard Worker                               size_t size,
196*8975f5c5SAndroid Build Coastguard Worker                               gl::BufferUsage usage);
197*8975f5c5SAndroid Build Coastguard Worker     angle::Result setSubDataImpl(const gl::Context *context,
198*8975f5c5SAndroid Build Coastguard Worker                                  const void *data,
199*8975f5c5SAndroid Build Coastguard Worker                                  size_t size,
200*8975f5c5SAndroid Build Coastguard Worker                                  size_t offset);
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker     angle::Result commitShadowCopy(ContextMtl *contextMtl);
203*8975f5c5SAndroid Build Coastguard Worker     angle::Result commitShadowCopy(ContextMtl *contextMtl, size_t size);
204*8975f5c5SAndroid Build Coastguard Worker 
205*8975f5c5SAndroid Build Coastguard Worker     void markConversionBuffersDirty();
206*8975f5c5SAndroid Build Coastguard Worker     void clearConversionBuffers();
207*8975f5c5SAndroid Build Coastguard Worker 
208*8975f5c5SAndroid Build Coastguard Worker     angle::Result putDataInNewBufferAndStartUsingNewBuffer(ContextMtl *contextMtl,
209*8975f5c5SAndroid Build Coastguard Worker                                                            const uint8_t *srcPtr,
210*8975f5c5SAndroid Build Coastguard Worker                                                            size_t sizeToCopy,
211*8975f5c5SAndroid Build Coastguard Worker                                                            size_t offset);
212*8975f5c5SAndroid Build Coastguard Worker     angle::Result updateExistingBufferViaBlitFromStagingBuffer(ContextMtl *contextMtl,
213*8975f5c5SAndroid Build Coastguard Worker                                                                const uint8_t *srcPtr,
214*8975f5c5SAndroid Build Coastguard Worker                                                                size_t sizeToCopy,
215*8975f5c5SAndroid Build Coastguard Worker                                                                size_t offset);
216*8975f5c5SAndroid Build Coastguard Worker     angle::Result copyDataToExistingBufferViaCPU(ContextMtl *contextMtl,
217*8975f5c5SAndroid Build Coastguard Worker                                                  const uint8_t *srcPtr,
218*8975f5c5SAndroid Build Coastguard Worker                                                  size_t sizeToCopy,
219*8975f5c5SAndroid Build Coastguard Worker                                                  size_t offset);
220*8975f5c5SAndroid Build Coastguard Worker     angle::Result updateShadowCopyThenCopyShadowToNewBuffer(ContextMtl *contextMtl,
221*8975f5c5SAndroid Build Coastguard Worker                                                             const uint8_t *srcPtr,
222*8975f5c5SAndroid Build Coastguard Worker                                                             size_t sizeToCopy,
223*8975f5c5SAndroid Build Coastguard Worker                                                             size_t offset);
224*8975f5c5SAndroid Build Coastguard Worker 
225*8975f5c5SAndroid Build Coastguard Worker     bool clientShadowCopyDataNeedSync(ContextMtl *contextMtl);
226*8975f5c5SAndroid Build Coastguard Worker     void ensureShadowCopySyncedFromGPU(ContextMtl *contextMtl);
227*8975f5c5SAndroid Build Coastguard Worker     uint8_t *syncAndObtainShadowCopy(ContextMtl *contextMtl);
228*8975f5c5SAndroid Build Coastguard Worker 
229*8975f5c5SAndroid Build Coastguard Worker     // Optional client side shadow buffer
230*8975f5c5SAndroid Build Coastguard Worker     angle::MemoryBuffer mShadowCopy;
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker     // A cache of converted vertex data.
233*8975f5c5SAndroid Build Coastguard Worker     std::vector<VertexConversionBufferMtl> mVertexConversionBuffers;
234*8975f5c5SAndroid Build Coastguard Worker 
235*8975f5c5SAndroid Build Coastguard Worker     std::vector<IndexConversionBufferMtl> mIndexConversionBuffers;
236*8975f5c5SAndroid Build Coastguard Worker 
237*8975f5c5SAndroid Build Coastguard Worker     std::vector<UniformConversionBufferMtl> mUniformConversionBuffers;
238*8975f5c5SAndroid Build Coastguard Worker 
239*8975f5c5SAndroid Build Coastguard Worker     struct RestartRangeCache
240*8975f5c5SAndroid Build Coastguard Worker     {
RestartRangeCacheRestartRangeCache241*8975f5c5SAndroid Build Coastguard Worker         RestartRangeCache(std::vector<IndexRange> &&ranges_, gl::DrawElementsType indexType_)
242*8975f5c5SAndroid Build Coastguard Worker             : ranges(ranges_), indexType(indexType_)
243*8975f5c5SAndroid Build Coastguard Worker         {}
244*8975f5c5SAndroid Build Coastguard Worker         const std::vector<IndexRange> ranges;
245*8975f5c5SAndroid Build Coastguard Worker         const gl::DrawElementsType indexType;
246*8975f5c5SAndroid Build Coastguard Worker     };
247*8975f5c5SAndroid Build Coastguard Worker     std::optional<RestartRangeCache> mRestartRangeCache;
248*8975f5c5SAndroid Build Coastguard Worker     std::vector<IndexRange> mRestartIndices;
249*8975f5c5SAndroid Build Coastguard Worker     size_t mGLSize        = 0;  // size GL asked for (vs size we actually allocated)
250*8975f5c5SAndroid Build Coastguard Worker     size_t mRevisionCount = 0;  // for generating labels only
251*8975f5c5SAndroid Build Coastguard Worker     gl::BufferUsage mUsage;
252*8975f5c5SAndroid Build Coastguard Worker };
253*8975f5c5SAndroid Build Coastguard Worker 
254*8975f5c5SAndroid Build Coastguard Worker class SimpleWeakBufferHolderMtl : public BufferHolderMtl
255*8975f5c5SAndroid Build Coastguard Worker {
256*8975f5c5SAndroid Build Coastguard Worker   public:
257*8975f5c5SAndroid Build Coastguard Worker     SimpleWeakBufferHolderMtl();
258*8975f5c5SAndroid Build Coastguard Worker 
set(const mtl::BufferRef & buffer)259*8975f5c5SAndroid Build Coastguard Worker     void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; }
260*8975f5c5SAndroid Build Coastguard Worker };
261*8975f5c5SAndroid Build Coastguard Worker 
262*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */
265