• 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 VkBufferUsageFlags GetDefaultBufferUsageFlags(RendererVk *renderer);
48 
49 class BufferVk : public BufferImpl
50 {
51   public:
52     BufferVk(const gl::BufferState &state);
53     ~BufferVk() override;
54     void destroy(const gl::Context *context) override;
55 
56     angle::Result setExternalBufferData(const gl::Context *context,
57                                         gl::BufferBinding target,
58                                         GLeglClientBufferEXT clientBuffer,
59                                         size_t size,
60                                         VkMemoryPropertyFlags memoryPropertyFlags);
61     angle::Result setDataWithUsageFlags(const gl::Context *context,
62                                         gl::BufferBinding target,
63                                         GLeglClientBufferEXT clientBuffer,
64                                         const void *data,
65                                         size_t size,
66                                         gl::BufferUsage usage,
67                                         GLbitfield flags) override;
68     angle::Result setData(const gl::Context *context,
69                           gl::BufferBinding target,
70                           const void *data,
71                           size_t size,
72                           gl::BufferUsage usage) override;
73     angle::Result setSubData(const gl::Context *context,
74                              gl::BufferBinding target,
75                              const void *data,
76                              size_t size,
77                              size_t offset) override;
78     angle::Result copySubData(const gl::Context *context,
79                               BufferImpl *source,
80                               GLintptr sourceOffset,
81                               GLintptr destOffset,
82                               GLsizeiptr size) override;
83     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
84     angle::Result mapRange(const gl::Context *context,
85                            size_t offset,
86                            size_t length,
87                            GLbitfield access,
88                            void **mapPtr) override;
89     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
90     angle::Result getSubData(const gl::Context *context,
91                              GLintptr offset,
92                              GLsizeiptr size,
93                              void *outData) override;
94 
95     angle::Result getIndexRange(const gl::Context *context,
96                                 gl::DrawElementsType type,
97                                 size_t offset,
98                                 size_t count,
99                                 bool primitiveRestartEnabled,
100                                 gl::IndexRange *outRange) override;
101 
getSize()102     GLint64 getSize() const { return mState.getSize(); }
103 
104     void onDataChanged() override;
105 
getBuffer()106     vk::BufferHelper &getBuffer()
107     {
108         ASSERT(isBufferValid());
109         // Always mark the BufferHelper as referenced by the GPU, whether or not there's a pending
110         // submission, since this function is only called when trying to get the underlying
111         // BufferHelper object so it can be used in a command.
112         mHasBeenReferencedByGPU = true;
113         return mBuffer;
114     }
115 
isBufferValid()116     bool isBufferValid() const { return mBuffer.valid(); }
117     bool isCurrentlyInUse(ContextVk *contextVk) const;
118 
119     angle::Result mapImpl(ContextVk *contextVk, GLbitfield access, void **mapPtr);
120     angle::Result mapRangeImpl(ContextVk *contextVk,
121                                VkDeviceSize offset,
122                                VkDeviceSize length,
123                                GLbitfield access,
124                                void **mapPtr);
125     angle::Result unmapImpl(ContextVk *contextVk);
126     angle::Result ghostMappedBuffer(ContextVk *contextVk,
127                                     VkDeviceSize offset,
128                                     VkDeviceSize length,
129                                     GLbitfield access,
130                                     void **mapPtr);
131 
132     ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer,
133                                                 angle::FormatID formatID,
134                                                 GLuint stride,
135                                                 size_t offset,
136                                                 bool hostVisible);
137 
138   private:
139     angle::Result updateBuffer(ContextVk *contextVk,
140                                const uint8_t *data,
141                                size_t size,
142                                size_t offset);
143     angle::Result directUpdate(ContextVk *contextVk,
144                                const uint8_t *data,
145                                size_t size,
146                                size_t offset);
147     angle::Result stagedUpdate(ContextVk *contextVk,
148                                const uint8_t *data,
149                                size_t size,
150                                size_t offset);
151     angle::Result allocStagingBuffer(ContextVk *contextVk,
152                                      vk::MemoryCoherency coherency,
153                                      VkDeviceSize size,
154                                      uint8_t **mapPtr);
155     angle::Result flushStagingBuffer(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size);
156     angle::Result acquireAndUpdate(ContextVk *contextVk,
157                                    const uint8_t *data,
158                                    size_t updateSize,
159                                    size_t offset,
160                                    BufferUpdateType updateType);
161     angle::Result setDataWithMemoryType(const gl::Context *context,
162                                         gl::BufferBinding target,
163                                         const void *data,
164                                         size_t size,
165                                         VkMemoryPropertyFlags memoryPropertyFlags,
166                                         bool persistentMapRequired,
167                                         gl::BufferUsage usage);
168     angle::Result handleDeviceLocalBufferMap(ContextVk *contextVk,
169                                              VkDeviceSize offset,
170                                              VkDeviceSize size,
171                                              uint8_t **mapPtr);
172     angle::Result setDataImpl(ContextVk *contextVk,
173                               const uint8_t *data,
174                               size_t size,
175                               size_t offset,
176                               BufferUpdateType updateType);
177     void release(ContextVk *context);
178     void dataUpdated();
179 
180     angle::Result acquireBufferHelper(ContextVk *contextVk,
181                                       size_t sizeInBytes,
182                                       BufferUpdateType updateType);
183 
isExternalBuffer()184     bool isExternalBuffer() const { return mClientBuffer != nullptr; }
185 
186     struct VertexConversionBuffer : public ConversionBuffer
187     {
188         VertexConversionBuffer(RendererVk *renderer,
189                                angle::FormatID formatIDIn,
190                                GLuint strideIn,
191                                size_t offsetIn,
192                                bool hostVisible);
193         ~VertexConversionBuffer();
194 
195         VertexConversionBuffer(VertexConversionBuffer &&other);
196 
197         // The conversion is identified by the triple of {format, stride, offset}.
198         angle::FormatID formatID;
199         GLuint stride;
200         size_t offset;
201     };
202 
203     vk::BufferHelper mBuffer;
204 
205     // If not null, this is the external memory pointer passed from client API.
206     void *mClientBuffer;
207 
208     uint32_t mMemoryTypeIndex;
209     // Memory/Usage property that will be used for memory allocation.
210     VkMemoryPropertyFlags mMemoryPropertyFlags;
211 
212     // The staging buffer to aid map operations. This is used when buffers are not host visible or
213     // for performance optimization when only a smaller range of buffer is mapped.
214     vk::BufferHelper mStagingBuffer;
215 
216     // A cache of converted vertex data.
217     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
218 
219     // Tracks whether mStagingBuffer has been mapped to user or not
220     bool mIsStagingBufferMapped;
221 
222     // Tracks if BufferVk object has valid data or not.
223     bool mHasValidData;
224 
225     // TODO: https://issuetracker.google.com/201826021 Remove this once we have a full fix.
226     // Tracks if BufferVk's data is ever been referenced by GPU since new storage has been
227     // allocated. Due to sub-allocation, we may get a new sub-allocated range in the same
228     // BufferHelper object. Because we track GPU progress by the BufferHelper object, this flag will
229     // help us to avoid detecting we are still GPU busy even though no one has used it yet since
230     // we got last sub-allocation.
231     bool mHasBeenReferencedByGPU;
232 };
233 
234 }  // namespace rx
235 
236 #endif  // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
237