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