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(isBufferValid()); 88 return *mBuffer; 89 } 90 getBuffer()91 vk::BufferHelper &getBuffer() 92 { 93 ASSERT(isBufferValid()); 94 return *mBuffer; 95 } 96 isBufferValid()97 bool isBufferValid() const { return mBuffer && mBuffer->valid(); } 98 99 angle::Result mapImpl(ContextVk *contextVk, void **mapPtr); 100 angle::Result mapRangeImpl(ContextVk *contextVk, 101 VkDeviceSize offset, 102 VkDeviceSize length, 103 GLbitfield access, 104 void **mapPtr); 105 angle::Result unmapImpl(ContextVk *contextVk); 106 107 // Calls copyBuffer internally. 108 angle::Result copyToBufferImpl(ContextVk *contextVk, 109 vk::BufferHelper *destBuffer, 110 uint32_t copyCount, 111 const VkBufferCopy *copies); 112 113 ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer, 114 angle::FormatID formatID, 115 GLuint stride, 116 size_t offset, 117 bool hostVisible); 118 119 private: 120 void initializeStagingBuffer(ContextVk *contextVk, gl::BufferBinding target, size_t size); 121 angle::Result initializeShadowBuffer(ContextVk *contextVk, 122 gl::BufferBinding target, 123 size_t size); 124 getShadowBuffer(size_t offset)125 ANGLE_INLINE uint8_t *getShadowBuffer(size_t offset) 126 { 127 return (mShadowBuffer.getCurrentBuffer() + offset); 128 } 129 getShadowBuffer(size_t offset)130 ANGLE_INLINE const uint8_t *getShadowBuffer(size_t offset) const 131 { 132 return (mShadowBuffer.getCurrentBuffer() + offset); 133 } 134 135 void updateShadowBuffer(const uint8_t *data, size_t size, size_t offset); 136 angle::Result directUpdate(ContextVk *contextVk, 137 const uint8_t *data, 138 size_t size, 139 size_t offset); 140 angle::Result stagedUpdate(ContextVk *contextVk, 141 const uint8_t *data, 142 size_t size, 143 size_t offset); 144 angle::Result acquireAndUpdate(ContextVk *contextVk, 145 const uint8_t *data, 146 size_t size, 147 size_t offset); 148 angle::Result setDataImpl(ContextVk *contextVk, 149 const uint8_t *data, 150 size_t size, 151 size_t offset); 152 void release(ContextVk *context); 153 void markConversionBuffersDirty(); 154 155 angle::Result acquireBufferHelper(ContextVk *contextVk, 156 size_t sizeInBytes, 157 vk::BufferHelper **bufferHelperOut); 158 159 struct VertexConversionBuffer : public ConversionBuffer 160 { 161 VertexConversionBuffer(RendererVk *renderer, 162 angle::FormatID formatIDIn, 163 GLuint strideIn, 164 size_t offsetIn, 165 bool hostVisible); 166 ~VertexConversionBuffer(); 167 168 VertexConversionBuffer(VertexConversionBuffer &&other); 169 170 // The conversion is identified by the triple of {format, stride, offset}. 171 angle::FormatID formatID; 172 GLuint stride; 173 size_t offset; 174 }; 175 176 vk::BufferHelper *mBuffer; 177 178 // Pool of BufferHelpers for mBuffer to acquire from 179 vk::DynamicBuffer mBufferPool; 180 181 // All staging buffer support is provided by a DynamicBuffer. 182 vk::DynamicBuffer mStagingBuffer; 183 184 // For GPU-read only buffers glMap* latency is reduced by maintaining a copy 185 // of the buffer which is writeable only by the CPU. The contents are updated on all 186 // glData/glSubData/glCopy calls. With this, a glMap* call becomes a non-blocking 187 // operation by elimnating the need to wait on any recorded or in-flight GPU commands. 188 // We use DynamicShadowBuffer class to encapsulate all the bookeeping logic. 189 vk::DynamicShadowBuffer mShadowBuffer; 190 191 // A cache of converted vertex data. 192 std::vector<VertexConversionBuffer> mVertexConversionBuffers; 193 }; 194 195 } // namespace rx 196 197 #endif // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_ 198