• 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()66     mtl::BufferRef getCurrentBuffer() { return mIsWeak ? mBufferWeakRef.lock() : mBuffer; }
67 
68   protected:
69     mtl::BufferRef mBuffer;
70     mtl::BufferWeakRef mBufferWeakRef;
71     bool mIsWeak = false;
72 };
73 
74 class BufferMtl : public BufferImpl, public BufferHolderMtl
75 {
76   public:
77     BufferMtl(const gl::BufferState &state);
78     ~BufferMtl() override;
79     void destroy(const gl::Context *context) override;
80 
81     angle::Result setData(const gl::Context *context,
82                           gl::BufferBinding target,
83                           const void *data,
84                           size_t size,
85                           gl::BufferUsage usage) override;
86     angle::Result setSubData(const gl::Context *context,
87                              gl::BufferBinding target,
88                              const void *data,
89                              size_t size,
90                              size_t offset) override;
91     angle::Result copySubData(const gl::Context *context,
92                               BufferImpl *source,
93                               GLintptr sourceOffset,
94                               GLintptr destOffset,
95                               GLsizeiptr size) override;
96     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
97     angle::Result mapRange(const gl::Context *context,
98                            size_t offset,
99                            size_t length,
100                            GLbitfield access,
101                            void **mapPtr) override;
102     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
103 
104     angle::Result getIndexRange(const gl::Context *context,
105                                 gl::DrawElementsType type,
106                                 size_t offset,
107                                 size_t count,
108                                 bool primitiveRestartEnabled,
109                                 gl::IndexRange *outRange) override;
110 
111     angle::Result getFirstLastIndices(gl::DrawElementsType type,
112                                       size_t offset,
113                                       size_t count,
114                                       std::pair<uint32_t, uint32_t> *outIndices) const;
115 
116     const uint8_t *getClientShadowCopyData(const gl::Context *context);
117 
118     ConversionBufferMtl *getVertexConversionBuffer(const gl::Context *context,
119                                                    angle::FormatID formatID,
120                                                    GLuint stride,
121                                                    size_t offset);
122 
123     IndexConversionBufferMtl *getIndexConversionBuffer(const gl::Context *context,
124                                                        gl::DrawElementsType type,
125                                                        size_t offset);
126 
size()127     size_t size() const { return static_cast<size_t>(mState.getSize()); }
128 
129   private:
130     angle::Result setSubDataImpl(const gl::Context *context,
131                                  const void *data,
132                                  size_t size,
133                                  size_t offset);
134 
135     angle::Result commitShadowCopy(const gl::Context *context);
136     angle::Result commitShadowCopy(const gl::Context *context, size_t size);
137 
138     void markConversionBuffersDirty();
139 
140     void clearConversionBuffers();
141 
142     // Client side shadow buffer
143     angle::MemoryBuffer mShadowCopy;
144 
145     // GPU side buffers pool
146     mtl::BufferPool mBufferPool;
147 
148     struct VertexConversionBuffer : public ConversionBufferMtl
149     {
150         VertexConversionBuffer(const gl::Context *context,
151                                angle::FormatID formatIDIn,
152                                GLuint strideIn,
153                                size_t offsetIn);
154 
155         // The conversion is identified by the triple of {format, stride, offset}.
156         angle::FormatID formatID;
157         GLuint stride;
158         size_t offset;
159     };
160 
161     // A cache of converted vertex data.
162     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
163 
164     std::vector<IndexConversionBufferMtl> mIndexConversionBuffers;
165 };
166 
167 class SimpleWeakBufferHolderMtl : public BufferHolderMtl
168 {
169   public:
170     SimpleWeakBufferHolderMtl();
171 
set(const mtl::BufferRef & buffer)172     void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; }
173 };
174 
175 }  // namespace rx
176 
177 #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */
178