// // Copyright 2016 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // BufferVk.h: // Defines the class interface for BufferVk, implementing BufferImpl. // #ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_ #define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_ #include "libANGLE/Buffer.h" #include "libANGLE/Observer.h" #include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/renderer/vulkan/vk_helpers.h" namespace rx { class RendererVk; // Conversion buffers hold translated index and vertex data. struct ConversionBuffer { ConversionBuffer(RendererVk *renderer, VkBufferUsageFlags usageFlags, size_t initialSize, size_t alignment, bool hostVisible); ~ConversionBuffer(); ConversionBuffer(ConversionBuffer &&other); // One state value determines if we need to re-stream vertex data. bool dirty; // One additional state value keeps the last allocation offset. VkDeviceSize lastAllocationOffset; // The conversion is stored in a dynamic buffer. vk::DynamicBuffer data; }; class BufferVk : public BufferImpl { public: BufferVk(const gl::BufferState &state); ~BufferVk() override; void destroy(const gl::Context *context) override; angle::Result setExternalBufferData(const gl::Context *context, gl::BufferBinding target, GLeglClientBufferEXT clientBuffer, size_t size, VkMemoryPropertyFlags memoryPropertyFlags); angle::Result setDataWithUsageFlags(const gl::Context *context, gl::BufferBinding target, GLeglClientBufferEXT clientBuffer, const void *data, size_t size, gl::BufferUsage usage, GLbitfield flags) override; angle::Result setData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, gl::BufferUsage usage) override; angle::Result setSubData(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, size_t offset) override; angle::Result copySubData(const gl::Context *context, BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) override; angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; angle::Result mapRange(const gl::Context *context, size_t offset, size_t length, GLbitfield access, void **mapPtr) override; angle::Result unmap(const gl::Context *context, GLboolean *result) override; angle::Result getSubData(const gl::Context *context, GLintptr offset, GLsizeiptr size, void *outData) override; angle::Result getIndexRange(const gl::Context *context, gl::DrawElementsType type, size_t offset, size_t count, bool primitiveRestartEnabled, gl::IndexRange *outRange) override; GLint64 getSize() const { return mState.getSize(); } void onDataChanged() override; const vk::BufferHelper &getBufferAndOffset(VkDeviceSize *offsetOut) const { ASSERT(isBufferValid()); *offsetOut = mBufferOffset; return *mBuffer; } vk::BufferHelper &getBufferAndOffset(VkDeviceSize *offsetOut) { ASSERT(isBufferValid()); *offsetOut = mBufferOffset; return *mBuffer; } bool isBufferValid() const { return mBuffer && mBuffer->valid(); } angle::Result mapImpl(ContextVk *contextVk, void **mapPtr); angle::Result mapRangeImpl(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize length, GLbitfield access, void **mapPtr); angle::Result unmapImpl(ContextVk *contextVk); ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer, angle::FormatID formatID, GLuint stride, size_t offset, bool hostVisible); private: angle::Result initializeShadowBuffer(ContextVk *contextVk, gl::BufferBinding target, size_t size); void initializeHostVisibleBufferPool(ContextVk *contextVk); ANGLE_INLINE uint8_t *getShadowBuffer(size_t offset) { return (mShadowBuffer.getCurrentBuffer() + offset); } ANGLE_INLINE const uint8_t *getShadowBuffer(size_t offset) const { return (mShadowBuffer.getCurrentBuffer() + offset); } void updateShadowBuffer(const uint8_t *data, size_t size, size_t offset); angle::Result updateBuffer(ContextVk *contextVk, const uint8_t *data, size_t size, size_t offset); angle::Result directUpdate(ContextVk *contextVk, const uint8_t *data, size_t size, size_t offset); angle::Result stagedUpdate(ContextVk *contextVk, const uint8_t *data, size_t size, size_t offset); angle::Result acquireAndUpdate(ContextVk *contextVk, const uint8_t *data, size_t updateSize, size_t offset); angle::Result setDataWithMemoryType(const gl::Context *context, gl::BufferBinding target, const void *data, size_t size, VkMemoryPropertyFlags memoryPropertyFlags, bool persistentMapRequired, gl::BufferUsage usage); angle::Result handleDeviceLocalBufferMap(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size, void **mapPtr); angle::Result handleDeviceLocalBufferUnmap(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size); angle::Result setDataImpl(ContextVk *contextVk, const uint8_t *data, size_t size, size_t offset); void release(ContextVk *context); void markConversionBuffersDirty(); angle::Result acquireBufferHelper(ContextVk *contextVk, size_t sizeInBytes); struct VertexConversionBuffer : public ConversionBuffer { VertexConversionBuffer(RendererVk *renderer, angle::FormatID formatIDIn, GLuint strideIn, size_t offsetIn, bool hostVisible); ~VertexConversionBuffer(); VertexConversionBuffer(VertexConversionBuffer &&other); // The conversion is identified by the triple of {format, stride, offset}. angle::FormatID formatID; GLuint stride; size_t offset; }; vk::BufferHelper *mBuffer; VkDeviceSize mBufferOffset; // Pool of BufferHelpers for mBuffer to acquire from vk::DynamicBuffer mBufferPool; // DynamicBuffer to aid map operations of buffers when they are not host visible. vk::DynamicBuffer mHostVisibleBufferPool; VkDeviceSize mHostVisibleBufferOffset; // For GPU-read only buffers glMap* latency is reduced by maintaining a copy // of the buffer which is writeable only by the CPU. The contents are updated on all // glData/glSubData/glCopy calls. With this, a glMap* call becomes a non-blocking // operation by elimnating the need to wait on any recorded or in-flight GPU commands. // We use DynamicShadowBuffer class to encapsulate all the bookeeping logic. vk::DynamicShadowBuffer mShadowBuffer; // A cache of converted vertex data. std::vector mVertexConversionBuffers; }; } // namespace rx #endif // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_