• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // BufferVk.h:
7 //    Defines the class interface for BufferVk, implementing BufferImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
12 
13 #include "libANGLE/Buffer.h"
14 #include "libANGLE/Observer.h"
15 #include "libANGLE/renderer/BufferImpl.h"
16 #include "libANGLE/renderer/vulkan/vk_helpers.h"
17 
18 namespace rx
19 {
20 class RendererVk;
21 
22 // Conversion buffers hold translated index and vertex data.
23 struct ConversionBuffer
24 {
25     ConversionBuffer(RendererVk *renderer,
26                      VkBufferUsageFlags usageFlags,
27                      size_t initialSize,
28                      size_t alignment,
29                      bool hostVisible);
30     ~ConversionBuffer();
31 
32     ConversionBuffer(ConversionBuffer &&other);
33 
34     // One state value determines if we need to re-stream vertex data.
35     bool dirty;
36 
37     // Where the conversion data is stored.
38     std::unique_ptr<vk::BufferHelper> data;
39 };
40 
41 enum class BufferUpdateType
42 {
43     StorageRedefined,
44     ContentsUpdate,
45 };
46 
47 struct BufferDataSource
48 {
49     // Buffer data can come from two sources:
50     // glBufferData and glBufferSubData upload through a CPU pointer
51     const void *data = nullptr;
52     // glCopyBufferSubData copies data from another buffer
53     vk::BufferHelper *buffer  = nullptr;
54     VkDeviceSize bufferOffset = 0;
55 };
56 
57 VkBufferUsageFlags GetDefaultBufferUsageFlags(RendererVk *renderer);
58 
59 class BufferVk : public BufferImpl
60 {
61   public:
62     BufferVk(const gl::BufferState &state);
63     ~BufferVk() override;
64     void destroy(const gl::Context *context) override;
65 
66     angle::Result setExternalBufferData(const gl::Context *context,
67                                         gl::BufferBinding target,
68                                         GLeglClientBufferEXT clientBuffer,
69                                         size_t size,
70                                         VkMemoryPropertyFlags memoryPropertyFlags);
71     angle::Result setDataWithUsageFlags(const gl::Context *context,
72                                         gl::BufferBinding target,
73                                         GLeglClientBufferEXT clientBuffer,
74                                         const void *data,
75                                         size_t size,
76                                         gl::BufferUsage usage,
77                                         GLbitfield flags) override;
78     angle::Result setData(const gl::Context *context,
79                           gl::BufferBinding target,
80                           const void *data,
81                           size_t size,
82                           gl::BufferUsage usage) override;
83     angle::Result setSubData(const gl::Context *context,
84                              gl::BufferBinding target,
85                              const void *data,
86                              size_t size,
87                              size_t offset) override;
88     angle::Result copySubData(const gl::Context *context,
89                               BufferImpl *source,
90                               GLintptr sourceOffset,
91                               GLintptr destOffset,
92                               GLsizeiptr size) override;
93     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
94     angle::Result mapRange(const gl::Context *context,
95                            size_t offset,
96                            size_t length,
97                            GLbitfield access,
98                            void **mapPtr) override;
99     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
100     angle::Result getSubData(const gl::Context *context,
101                              GLintptr offset,
102                              GLsizeiptr size,
103                              void *outData) override;
104 
105     angle::Result getIndexRange(const gl::Context *context,
106                                 gl::DrawElementsType type,
107                                 size_t offset,
108                                 size_t count,
109                                 bool primitiveRestartEnabled,
110                                 gl::IndexRange *outRange) override;
111 
getSize()112     GLint64 getSize() const { return mState.getSize(); }
113 
114     void onDataChanged() override;
115 
getBuffer()116     vk::BufferHelper &getBuffer()
117     {
118         ASSERT(isBufferValid());
119         return mBuffer;
120     }
121 
getBufferSerial()122     vk::BufferSerial getBufferSerial() { return mBuffer.getBufferSerial(); }
123 
isBufferValid()124     bool isBufferValid() const { return mBuffer.valid(); }
125     bool isCurrentlyInUse(RendererVk *renderer) const;
126 
127     angle::Result mapImpl(ContextVk *contextVk, GLbitfield access, void **mapPtr);
128     angle::Result mapRangeImpl(ContextVk *contextVk,
129                                VkDeviceSize offset,
130                                VkDeviceSize length,
131                                GLbitfield access,
132                                void **mapPtr);
133     angle::Result unmapImpl(ContextVk *contextVk);
134     angle::Result ghostMappedBuffer(ContextVk *contextVk,
135                                     VkDeviceSize offset,
136                                     VkDeviceSize length,
137                                     GLbitfield access,
138                                     void **mapPtr);
139 
140     ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer,
141                                                 angle::FormatID formatID,
142                                                 GLuint stride,
143                                                 size_t offset,
144                                                 bool hostVisible);
145 
146   private:
147     angle::Result updateBuffer(ContextVk *contextVk,
148                                size_t bufferSize,
149                                const BufferDataSource &dataSource,
150                                size_t size,
151                                size_t offset);
152     angle::Result directUpdate(ContextVk *contextVk,
153                                const BufferDataSource &dataSource,
154                                size_t size,
155                                size_t offset);
156     angle::Result stagedUpdate(ContextVk *contextVk,
157                                const BufferDataSource &dataSource,
158                                size_t size,
159                                size_t offset);
160     angle::Result allocStagingBuffer(ContextVk *contextVk,
161                                      vk::MemoryCoherency coherency,
162                                      VkDeviceSize size,
163                                      uint8_t **mapPtr);
164     angle::Result flushStagingBuffer(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size);
165     angle::Result acquireAndUpdate(ContextVk *contextVk,
166                                    size_t bufferSize,
167                                    const BufferDataSource &dataSource,
168                                    size_t updateSize,
169                                    size_t updateOffset,
170                                    BufferUpdateType updateType);
171     angle::Result setDataWithMemoryType(const gl::Context *context,
172                                         gl::BufferBinding target,
173                                         const void *data,
174                                         size_t size,
175                                         VkMemoryPropertyFlags memoryPropertyFlags,
176                                         gl::BufferUsage usage);
177     angle::Result handleDeviceLocalBufferMap(ContextVk *contextVk,
178                                              VkDeviceSize offset,
179                                              VkDeviceSize size,
180                                              uint8_t **mapPtr);
181     angle::Result setDataImpl(ContextVk *contextVk,
182                               size_t bufferSize,
183                               const BufferDataSource &dataSource,
184                               size_t updateSize,
185                               size_t updateOffset,
186                               BufferUpdateType updateType);
187     void release(ContextVk *context);
188     void dataUpdated();
189 
190     angle::Result acquireBufferHelper(ContextVk *contextVk,
191                                       size_t sizeInBytes,
192                                       BufferUsageType usageType);
193 
isExternalBuffer()194     bool isExternalBuffer() const { return mClientBuffer != nullptr; }
195     BufferUpdateType calculateBufferUpdateTypeOnFullUpdate(
196         RendererVk *renderer,
197         size_t size,
198         VkMemoryPropertyFlags memoryPropertyFlags,
199         BufferUsageType usageType,
200         const void *data) const;
201     bool shouldRedefineStorage(RendererVk *renderer,
202                                BufferUsageType usageType,
203                                VkMemoryPropertyFlags memoryPropertyFlags,
204                                size_t size) const;
205 
206     struct VertexConversionBuffer : public ConversionBuffer
207     {
208         VertexConversionBuffer(RendererVk *renderer,
209                                angle::FormatID formatIDIn,
210                                GLuint strideIn,
211                                size_t offsetIn,
212                                bool hostVisible);
213         ~VertexConversionBuffer();
214 
215         VertexConversionBuffer(VertexConversionBuffer &&other);
216 
217         // The conversion is identified by the triple of {format, stride, offset}.
218         angle::FormatID formatID;
219         GLuint stride;
220         size_t offset;
221     };
222 
223     vk::BufferHelper mBuffer;
224 
225     // If not null, this is the external memory pointer passed from client API.
226     void *mClientBuffer;
227 
228     uint32_t mMemoryTypeIndex;
229     // Memory/Usage property that will be used for memory allocation.
230     VkMemoryPropertyFlags mMemoryPropertyFlags;
231 
232     // The staging buffer to aid map operations. This is used when buffers are not host visible or
233     // for performance optimization when only a smaller range of buffer is mapped.
234     vk::BufferHelper mStagingBuffer;
235 
236     // A cache of converted vertex data.
237     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
238 
239     // Tracks whether mStagingBuffer has been mapped to user or not
240     bool mIsStagingBufferMapped;
241 
242     // Tracks if BufferVk object has valid data or not.
243     bool mHasValidData;
244 
245     // True if the buffer is currently mapped for CPU write access. If the map call is originated
246     // from OpenGLES API call, then this should be consistent with mState.getAccessFlags() bits.
247     // Otherwise it is mapped from ANGLE internal and will not be consistent with mState access
248     // bits, so we have to keep record of it.
249     bool mIsMappedForWrite;
250     // True if usage is dynamic. May affect how we allocate memory.
251     BufferUsageType mUsageType;
252     // Similar as mIsMappedForWrite, this maybe different from mState's getMapOffset/getMapLength if
253     // mapped from angle internal.
254     VkDeviceSize mMappedOffset;
255     VkDeviceSize mMappedLength;
256 };
257 
258 }  // namespace rx
259 
260 #endif  // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
261