• 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 setData(const gl::Context *context,
52                           gl::BufferBinding target,
53                           const void *data,
54                           size_t size,
55                           gl::BufferUsage usage) override;
56     angle::Result setSubData(const gl::Context *context,
57                              gl::BufferBinding target,
58                              const void *data,
59                              size_t size,
60                              size_t offset) override;
61     angle::Result copySubData(const gl::Context *context,
62                               BufferImpl *source,
63                               GLintptr sourceOffset,
64                               GLintptr destOffset,
65                               GLsizeiptr size) override;
66     angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
67     angle::Result mapRange(const gl::Context *context,
68                            size_t offset,
69                            size_t length,
70                            GLbitfield access,
71                            void **mapPtr) override;
72     angle::Result unmap(const gl::Context *context, GLboolean *result) override;
73 
74     angle::Result getIndexRange(const gl::Context *context,
75                                 gl::DrawElementsType type,
76                                 size_t offset,
77                                 size_t count,
78                                 bool primitiveRestartEnabled,
79                                 gl::IndexRange *outRange) override;
80 
getSize()81     GLint64 getSize() const { return mState.getSize(); }
82 
83     void onDataChanged() override;
84 
getBuffer()85     const vk::BufferHelper &getBuffer() const
86     {
87         ASSERT(mBuffer.valid());
88         return mBuffer;
89     }
90 
getBuffer()91     vk::BufferHelper &getBuffer()
92     {
93         ASSERT(mBuffer.valid());
94         return mBuffer;
95     }
96 
97     angle::Result mapImpl(ContextVk *contextVk, void **mapPtr);
98     angle::Result mapRangeImpl(ContextVk *contextVk,
99                                VkDeviceSize offset,
100                                VkDeviceSize length,
101                                GLbitfield access,
102                                void **mapPtr);
103     angle::Result unmapImpl(ContextVk *contextVk);
104 
105     // Calls copyBuffer internally.
106     angle::Result copyToBufferImpl(ContextVk *contextVk,
107                                    vk::BufferHelper *destBuffer,
108                                    uint32_t copyCount,
109                                    const VkBufferCopy *copies);
110 
111     ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer,
112                                                 angle::FormatID formatID,
113                                                 GLuint stride,
114                                                 size_t offset,
115                                                 bool hostVisible);
116 
117   private:
118     void initializeStagingBuffer(ContextVk *contextVk, gl::BufferBinding target, size_t size);
119     angle::Result initializeShadowBuffer(ContextVk *contextVk,
120                                          gl::BufferBinding target,
121                                          size_t size);
122 
getShadowBuffer(size_t offset)123     ANGLE_INLINE uint8_t *getShadowBuffer(size_t offset)
124     {
125         return (mShadowBuffer.getCurrentBuffer() + offset);
126     }
127 
getShadowBuffer(size_t offset)128     ANGLE_INLINE const uint8_t *getShadowBuffer(size_t offset) const
129     {
130         return (mShadowBuffer.getCurrentBuffer() + offset);
131     }
132 
133     void updateShadowBuffer(const uint8_t *data, size_t size, size_t offset);
134     angle::Result directUpdate(ContextVk *contextVk,
135                                const uint8_t *data,
136                                size_t size,
137                                size_t offset);
138     angle::Result stagedUpdate(ContextVk *contextVk,
139                                const uint8_t *data,
140                                size_t size,
141                                size_t offset);
142     angle::Result setDataImpl(ContextVk *contextVk,
143                               const uint8_t *data,
144                               size_t size,
145                               size_t offset);
146     void release(ContextVk *context);
147     void markConversionBuffersDirty();
148 
149     struct VertexConversionBuffer : public ConversionBuffer
150     {
151         VertexConversionBuffer(RendererVk *renderer,
152                                angle::FormatID formatIDIn,
153                                GLuint strideIn,
154                                size_t offsetIn,
155                                bool hostVisible);
156         ~VertexConversionBuffer();
157 
158         VertexConversionBuffer(VertexConversionBuffer &&other);
159 
160         // The conversion is identified by the triple of {format, stride, offset}.
161         angle::FormatID formatID;
162         GLuint stride;
163         size_t offset;
164     };
165 
166     vk::BufferHelper mBuffer;
167 
168     // All staging buffer support is provided by a DynamicBuffer.
169     vk::DynamicBuffer mStagingBuffer;
170 
171     // For GPU-read only buffers glMap* latency is reduced by maintaining a copy
172     // of the buffer which is writeable only by the CPU. The contents are updated on all
173     // glData/glSubData/glCopy calls. With this, a glMap* call becomes a non-blocking
174     // operation by elimnating the need to wait on any recorded or in-flight GPU commands.
175     // We use DynamicShadowBuffer class to encapsulate all the bookeeping logic.
176     vk::DynamicShadowBuffer mShadowBuffer;
177 
178     // A cache of converted vertex data.
179     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
180 };
181 
182 }  // namespace rx
183 
184 #endif  // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
185