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