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