• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // BufferMtl.h:
7 //    Defines the class interface for BufferMtl, implementing BufferImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_METAL_BUFFERMTL_H_
11 #define LIBANGLE_RENDERER_METAL_BUFFERMTL_H_
12 
13 #import <Metal/Metal.h>
14 
15 #include <utility>
16 
17 #include "libANGLE/Buffer.h"
18 #include "libANGLE/Observer.h"
19 #include "libANGLE/angletypes.h"
20 #include "libANGLE/renderer/BufferImpl.h"
21 #include "libANGLE/renderer/Format.h"
22 #include "libANGLE/renderer/metal/mtl_buffer_pool.h"
23 #include "libANGLE/renderer/metal/mtl_resources.h"
24 
25 namespace rx
26 {
27 struct IndexRange
28 {
29     size_t restartBegin;
30     size_t restartEnd;
31 };
32 // Conversion buffers hold translated index and vertex data.
33 struct ConversionBufferMtl
34 {
35     ConversionBufferMtl(ContextMtl *context, size_t initialSize, size_t alignment);
36     ~ConversionBufferMtl();
37 
38     // One state value determines if we need to re-stream vertex data.
39     bool dirty;
40 
41     // The conversion is stored in a dynamic buffer.
42     mtl::BufferPool data;
43     // These properties are to be filled by user of this buffer conversion
44     mtl::BufferRef convertedBuffer;
45     size_t convertedOffset;
46 };
47 
48 struct VertexConversionBufferMtl : public ConversionBufferMtl
49 {
50     VertexConversionBufferMtl(ContextMtl *context,
51                               angle::FormatID formatIDIn,
52                               GLuint strideIn,
53                               size_t offsetIn);
54 
55     // The conversion is identified by the triple of {format, stride, offset}.
56     angle::FormatID formatID;
57     GLuint stride;
58     size_t offset;
59 };
60 
61 struct IndexConversionBufferMtl : public ConversionBufferMtl
62 {
63     IndexConversionBufferMtl(ContextMtl *context,
64                              gl::DrawElementsType elemType,
65                              bool primitiveRestartEnabled,
66                              size_t offsetIn,
67                              std::vector<IndexRange> restartRangesIn = std::vector<IndexRange>());
68     const gl::DrawElementsType elemType;
69     const size_t offset;
70     bool primitiveRestartEnabled;
71     std::vector<IndexRange> restartRanges;
72     IndexRange getRangeForConvertedBuffer(size_t count);
73 };
74 
75 struct UniformConversionBufferMtl : public ConversionBufferMtl
76 {
77     UniformConversionBufferMtl(ContextMtl *context, size_t offsetIn);
78 
79     const size_t offset;
80 };
81 
82 class BufferHolderMtl
83 {
84   public:
85     virtual ~BufferHolderMtl() = default;
86 
87     // Due to the complication of synchronizing accesses between CPU and GPU,
88     // a mtl::Buffer might be under used by GPU but CPU wants to modify its content through
89     // map() method, this could lead to GPU stalling. The more efficient method is maintain
90     // a queue of mtl::Buffer and only let CPU modifies a free mtl::Buffer.
91     // So, in order to let GPU use the most recent modified content, one must call this method
92     // right before the draw call to retrieved the most up-to-date mtl::Buffer.
getCurrentBuffer()93     mtl::BufferRef getCurrentBuffer() { return mIsWeak ? mBufferWeakRef.lock() : mBuffer; }
94 
95   protected:
96     mtl::BufferRef mBuffer;
97     mtl::BufferWeakRef mBufferWeakRef;
98     bool mIsWeak = false;
99 };
100 
101 class BufferMtl : public BufferImpl, public BufferHolderMtl
102 {
103   public:
104     BufferMtl(const gl::BufferState &state);
105     ~BufferMtl() override;
106     void destroy(const gl::Context *context) override;
107 
108     angle::Result setData(const gl::Context *context,
109                           gl::BufferBinding target,
110                           const void *data,
111                           size_t size,
112                           gl::BufferUsage usage) override;
113     angle::Result setSubData(const gl::Context *context,
114                              gl::BufferBinding target,
115                              const void *data,
116                              size_t size,
117                              size_t offset) override;
118     angle::Result copySubData(const gl::Context *context,
119                               BufferImpl *source,
120                               GLintptr sourceOffset,
121                               GLintptr destOffset,
122                               GLsizeiptr size) override;
123     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
124     angle::Result mapRange(const gl::Context *context,
125                            size_t offset,
126                            size_t length,
127                            GLbitfield access,
128                            void **mapPtr) override;
129     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
130 
131     angle::Result getIndexRange(const gl::Context *context,
132                                 gl::DrawElementsType type,
133                                 size_t offset,
134                                 size_t count,
135                                 bool primitiveRestartEnabled,
136                                 gl::IndexRange *outRange) override;
137 
138     void onDataChanged() override;
139 
140     angle::Result getFirstLastIndices(ContextMtl *contextMtl,
141                                       gl::DrawElementsType type,
142                                       size_t offset,
143                                       size_t count,
144                                       std::pair<uint32_t, uint32_t> *outIndices);
145 
146     const uint8_t *getClientShadowCopyData(ContextMtl *contextMtl);
147 
148     ConversionBufferMtl *getVertexConversionBuffer(ContextMtl *context,
149                                                    angle::FormatID formatID,
150                                                    GLuint stride,
151                                                    size_t offset);
152 
153     IndexConversionBufferMtl *getIndexConversionBuffer(ContextMtl *context,
154                                                        gl::DrawElementsType elemType,
155                                                        bool primitiveRestartEnabled,
156                                                        size_t offset);
157 
158     ConversionBufferMtl *getUniformConversionBuffer(ContextMtl *context, size_t offset);
159 
size()160     size_t size() const { return static_cast<size_t>(mState.getSize()); }
161 
162   private:
163     angle::Result setDataImpl(const gl::Context *context,
164                               gl::BufferBinding target,
165                               const void *data,
166                               size_t size,
167                               gl::BufferUsage usage);
168     angle::Result setSubDataImpl(const gl::Context *context,
169                                  const void *data,
170                                  size_t size,
171                                  size_t offset);
172 
173     angle::Result commitShadowCopy(const gl::Context *context);
174     angle::Result commitShadowCopy(const gl::Context *context, size_t size);
175 
176     void markConversionBuffersDirty();
177 
178     void clearConversionBuffers();
179     bool clientShadowCopyDataNeedSync(ContextMtl *contextMtl);
180     void ensureShadowCopySyncedFromGPU(ContextMtl *contextMtl);
181     uint8_t *syncAndObtainShadowCopy(ContextMtl *contextMtl);
182 
183     // Convenient method
getClientShadowCopyData(const gl::Context * context)184     const uint8_t *getClientShadowCopyData(const gl::Context *context)
185     {
186         return getClientShadowCopyData(mtl::GetImpl(context));
187     }
188     // Client side shadow buffer
189     angle::MemoryBuffer mShadowCopy;
190 
191     // GPU side buffers pool
192     mtl::BufferPool mBufferPool;
193 
194     // A cache of converted vertex data.
195     std::vector<VertexConversionBufferMtl> mVertexConversionBuffers;
196 
197     std::vector<IndexConversionBufferMtl> mIndexConversionBuffers;
198 
199     std::vector<UniformConversionBufferMtl> mUniformConversionBuffers;
200 };
201 
202 class SimpleWeakBufferHolderMtl : public BufferHolderMtl
203 {
204   public:
205     SimpleWeakBufferHolderMtl();
206 
set(const mtl::BufferRef & buffer)207     void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; }
208 };
209 
210 }  // namespace rx
211 
212 #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */
213