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