• 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 
28 // Conversion buffers hold translated index and vertex data.
29 struct ConversionBufferMtl
30 {
31     ConversionBufferMtl(const gl::Context *context, size_t initialSize, size_t alignment);
32     ~ConversionBufferMtl();
33 
34     // One state value determines if we need to re-stream vertex data.
35     bool dirty;
36 
37     // The conversion is stored in a dynamic buffer.
38     mtl::BufferPool data;
39 
40     // These properties are to be filled by user of this buffer conversion
41     mtl::BufferRef convertedBuffer;
42     size_t convertedOffset;
43 };
44 
45 struct IndexConversionBufferMtl : public ConversionBufferMtl
46 {
47     IndexConversionBufferMtl(const gl::Context *context,
48                              gl::DrawElementsType type,
49                              size_t offsetIn);
50 
51     const gl::DrawElementsType type;
52     const size_t offset;
53 };
54 
55 class BufferHolderMtl
56 {
57   public:
58     virtual ~BufferHolderMtl() = default;
59 
60     // Due to the complication of synchronizing accesses between CPU and GPU,
61     // a mtl::Buffer might be under used by GPU but CPU wants to modify its content through
62     // map() method, this could lead to GPU stalling. The more efficient method is maintain
63     // a queue of mtl::Buffer and only let CPU modifies a free mtl::Buffer.
64     // So, in order to let GPU use the most recent modified content, one must call this method
65     // right before the draw call to retrieved the most up-to-date mtl::Buffer.
getCurrentBuffer(const gl::Context * context)66     mtl::BufferRef getCurrentBuffer(const gl::Context *context)
67     {
68         return mIsWeak ? mBufferWeakRef.lock() : mBuffer;
69     }
70 
71   protected:
72     mtl::BufferRef mBuffer;
73     mtl::BufferWeakRef mBufferWeakRef;
74     bool mIsWeak = false;
75 };
76 
77 class BufferMtl : public BufferImpl, public BufferHolderMtl
78 {
79   public:
80     BufferMtl(const gl::BufferState &state);
81     ~BufferMtl() override;
82     void destroy(const gl::Context *context) override;
83 
84     angle::Result setData(const gl::Context *context,
85                           gl::BufferBinding target,
86                           const void *data,
87                           size_t size,
88                           gl::BufferUsage usage) override;
89     angle::Result setSubData(const gl::Context *context,
90                              gl::BufferBinding target,
91                              const void *data,
92                              size_t size,
93                              size_t offset) override;
94     angle::Result copySubData(const gl::Context *context,
95                               BufferImpl *source,
96                               GLintptr sourceOffset,
97                               GLintptr destOffset,
98                               GLsizeiptr size) override;
99     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
100     angle::Result mapRange(const gl::Context *context,
101                            size_t offset,
102                            size_t length,
103                            GLbitfield access,
104                            void **mapPtr) override;
105     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
106 
107     angle::Result getIndexRange(const gl::Context *context,
108                                 gl::DrawElementsType type,
109                                 size_t offset,
110                                 size_t count,
111                                 bool primitiveRestartEnabled,
112                                 gl::IndexRange *outRange) override;
113 
114     angle::Result getFirstLastIndices(const gl::Context *context,
115                                       gl::DrawElementsType type,
116                                       size_t offset,
117                                       size_t count,
118                                       std::pair<uint32_t, uint32_t> *outIndices) const;
119 
120     const uint8_t *getClientShadowCopyData(const gl::Context *context);
121 
122     ConversionBufferMtl *getVertexConversionBuffer(const gl::Context *context,
123                                                    angle::FormatID formatID,
124                                                    GLuint stride,
125                                                    size_t offset);
126 
127     IndexConversionBufferMtl *getIndexConversionBuffer(const gl::Context *context,
128                                                        gl::DrawElementsType type,
129                                                        size_t offset);
130 
size()131     size_t size() const { return static_cast<size_t>(mState.getSize()); }
132 
133   private:
134     angle::Result setSubDataImpl(const gl::Context *context,
135                                  const void *data,
136                                  size_t size,
137                                  size_t offset);
138 
139     angle::Result commitShadowCopy(const gl::Context *context);
140     angle::Result commitShadowCopy(const gl::Context *context, size_t size);
141 
142     void markConversionBuffersDirty();
143 
144     void clearConversionBuffers();
145 
146     // Client side shadow buffer
147     angle::MemoryBuffer mShadowCopy;
148 
149     // GPU side buffers pool
150     mtl::BufferPool mBufferPool;
151 
152     struct VertexConversionBuffer : public ConversionBufferMtl
153     {
154         VertexConversionBuffer(const gl::Context *context,
155                                angle::FormatID formatIDIn,
156                                GLuint strideIn,
157                                size_t offsetIn);
158 
159         // The conversion is identified by the triple of {format, stride, offset}.
160         angle::FormatID formatID;
161         GLuint stride;
162         size_t offset;
163     };
164 
165     // A cache of converted vertex data.
166     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
167 
168     std::vector<IndexConversionBufferMtl> mIndexConversionBuffers;
169 };
170 
171 class SimpleWeakBufferHolderMtl : public BufferHolderMtl
172 {
173   public:
174     SimpleWeakBufferHolderMtl();
175 
set(const mtl::BufferRef & buffer)176     void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; }
177 };
178 
179 }  // namespace rx
180 
181 #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */
182