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