• 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     // One additional state value keeps the last allocation offset.
38     VkDeviceSize lastAllocationOffset;
39 
40     // The conversion is stored in a dynamic buffer.
41     vk::DynamicBuffer data;
42 };
43 
44 class BufferVk : public BufferImpl
45 {
46   public:
47     BufferVk(const gl::BufferState &state);
48     ~BufferVk() override;
49     void destroy(const gl::Context *context) override;
50 
51     angle::Result setExternalBufferData(const gl::Context *context,
52                                         gl::BufferBinding target,
53                                         GLeglClientBufferEXT clientBuffer,
54                                         size_t size,
55                                         VkMemoryPropertyFlags memoryPropertyFlags);
56     angle::Result setDataWithUsageFlags(const gl::Context *context,
57                                         gl::BufferBinding target,
58                                         GLeglClientBufferEXT clientBuffer,
59                                         const void *data,
60                                         size_t size,
61                                         gl::BufferUsage usage,
62                                         GLbitfield flags) override;
63     angle::Result setData(const gl::Context *context,
64                           gl::BufferBinding target,
65                           const void *data,
66                           size_t size,
67                           gl::BufferUsage usage) override;
68     angle::Result setSubData(const gl::Context *context,
69                              gl::BufferBinding target,
70                              const void *data,
71                              size_t size,
72                              size_t offset) override;
73     angle::Result copySubData(const gl::Context *context,
74                               BufferImpl *source,
75                               GLintptr sourceOffset,
76                               GLintptr destOffset,
77                               GLsizeiptr size) override;
78     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
79     angle::Result mapRange(const gl::Context *context,
80                            size_t offset,
81                            size_t length,
82                            GLbitfield access,
83                            void **mapPtr) override;
84     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
85     angle::Result getSubData(const gl::Context *context,
86                              GLintptr offset,
87                              GLsizeiptr size,
88                              void *outData) override;
89 
90     angle::Result getIndexRange(const gl::Context *context,
91                                 gl::DrawElementsType type,
92                                 size_t offset,
93                                 size_t count,
94                                 bool primitiveRestartEnabled,
95                                 gl::IndexRange *outRange) override;
96 
getSize()97     GLint64 getSize() const { return mState.getSize(); }
98 
99     void onDataChanged() override;
100 
getBufferAndOffset(VkDeviceSize * offsetOut)101     const vk::BufferHelper &getBufferAndOffset(VkDeviceSize *offsetOut) const
102     {
103         ASSERT(isBufferValid());
104         *offsetOut = mBufferOffset;
105         return *mBuffer;
106     }
107 
getBufferAndOffset(VkDeviceSize * offsetOut)108     vk::BufferHelper &getBufferAndOffset(VkDeviceSize *offsetOut)
109     {
110         ASSERT(isBufferValid());
111         *offsetOut = mBufferOffset;
112         return *mBuffer;
113     }
114 
isBufferValid()115     bool isBufferValid() const { return mBuffer && mBuffer->valid(); }
116 
117     angle::Result mapImpl(ContextVk *contextVk, void **mapPtr);
118     angle::Result mapRangeImpl(ContextVk *contextVk,
119                                VkDeviceSize offset,
120                                VkDeviceSize length,
121                                GLbitfield access,
122                                void **mapPtr);
123     angle::Result unmapImpl(ContextVk *contextVk);
124 
125     ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer,
126                                                 angle::FormatID formatID,
127                                                 GLuint stride,
128                                                 size_t offset,
129                                                 bool hostVisible);
130 
131   private:
132     angle::Result initializeShadowBuffer(ContextVk *contextVk,
133                                          gl::BufferBinding target,
134                                          size_t size);
135     void initializeHostVisibleBufferPool(ContextVk *contextVk);
136 
getShadowBuffer(size_t offset)137     ANGLE_INLINE uint8_t *getShadowBuffer(size_t offset)
138     {
139         return (mShadowBuffer.getCurrentBuffer() + offset);
140     }
141 
getShadowBuffer(size_t offset)142     ANGLE_INLINE const uint8_t *getShadowBuffer(size_t offset) const
143     {
144         return (mShadowBuffer.getCurrentBuffer() + offset);
145     }
146 
147     void updateShadowBuffer(const uint8_t *data, size_t size, size_t offset);
148     angle::Result updateBuffer(ContextVk *contextVk,
149                                const uint8_t *data,
150                                size_t size,
151                                size_t offset);
152     angle::Result directUpdate(ContextVk *contextVk,
153                                const uint8_t *data,
154                                size_t size,
155                                size_t offset);
156     angle::Result stagedUpdate(ContextVk *contextVk,
157                                const uint8_t *data,
158                                size_t size,
159                                size_t offset);
160     angle::Result acquireAndUpdate(ContextVk *contextVk,
161                                    const uint8_t *data,
162                                    size_t updateSize,
163                                    size_t offset);
164     angle::Result setDataWithMemoryType(const gl::Context *context,
165                                         gl::BufferBinding target,
166                                         const void *data,
167                                         size_t size,
168                                         VkMemoryPropertyFlags memoryPropertyFlags,
169                                         bool persistentMapRequired,
170                                         gl::BufferUsage usage);
171     angle::Result handleDeviceLocalBufferMap(ContextVk *contextVk,
172                                              VkDeviceSize offset,
173                                              VkDeviceSize size,
174                                              void **mapPtr);
175     angle::Result handleDeviceLocalBufferUnmap(ContextVk *contextVk,
176                                                VkDeviceSize offset,
177                                                VkDeviceSize size);
178     angle::Result setDataImpl(ContextVk *contextVk,
179                               const uint8_t *data,
180                               size_t size,
181                               size_t offset);
182     void release(ContextVk *context);
183     void markConversionBuffersDirty();
184 
185     angle::Result acquireBufferHelper(ContextVk *contextVk, size_t sizeInBytes);
186 
187     struct VertexConversionBuffer : public ConversionBuffer
188     {
189         VertexConversionBuffer(RendererVk *renderer,
190                                angle::FormatID formatIDIn,
191                                GLuint strideIn,
192                                size_t offsetIn,
193                                bool hostVisible);
194         ~VertexConversionBuffer();
195 
196         VertexConversionBuffer(VertexConversionBuffer &&other);
197 
198         // The conversion is identified by the triple of {format, stride, offset}.
199         angle::FormatID formatID;
200         GLuint stride;
201         size_t offset;
202     };
203 
204     vk::BufferHelper *mBuffer;
205     VkDeviceSize mBufferOffset;
206 
207     // Pool of BufferHelpers for mBuffer to acquire from
208     vk::DynamicBuffer mBufferPool;
209 
210     // DynamicBuffer to aid map operations of buffers when they are not host visible.
211     vk::DynamicBuffer mHostVisibleBufferPool;
212     VkDeviceSize mHostVisibleBufferOffset;
213 
214     // For GPU-read only buffers glMap* latency is reduced by maintaining a copy
215     // of the buffer which is writeable only by the CPU. The contents are updated on all
216     // glData/glSubData/glCopy calls. With this, a glMap* call becomes a non-blocking
217     // operation by elimnating the need to wait on any recorded or in-flight GPU commands.
218     // We use DynamicShadowBuffer class to encapsulate all the bookeeping logic.
219     vk::DynamicShadowBuffer mShadowBuffer;
220 
221     // A cache of converted vertex data.
222     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
223 };
224 
225 }  // namespace rx
226 
227 #endif  // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
228