1 // 2 // Copyright 2019 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 // BufferMtl.h: 7 // Defines the class interface for BufferMtl, implementing BufferImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ 11 #define LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ 12 13 #import <Metal/Metal.h> 14 15 #include <utility> 16 17 #include "libANGLE/Buffer.h" 18 #include "libANGLE/Observer.h" 19 #include "libANGLE/angletypes.h" 20 #include "libANGLE/renderer/BufferImpl.h" 21 #include "libANGLE/renderer/Format.h" 22 #include "libANGLE/renderer/metal/mtl_buffer_pool.h" 23 #include "libANGLE/renderer/metal/mtl_resources.h" 24 25 namespace rx 26 { 27 28 // Conversion buffers hold translated index and vertex data. 29 struct ConversionBufferMtl 30 { 31 ConversionBufferMtl(const gl::Context *context, size_t initialSize, size_t alignment); 32 ~ConversionBufferMtl(); 33 34 // One state value determines if we need to re-stream vertex data. 35 bool dirty; 36 37 // The conversion is stored in a dynamic buffer. 38 mtl::BufferPool data; 39 40 // These properties are to be filled by user of this buffer conversion 41 mtl::BufferRef convertedBuffer; 42 size_t convertedOffset; 43 }; 44 45 struct IndexConversionBufferMtl : public ConversionBufferMtl 46 { 47 IndexConversionBufferMtl(const gl::Context *context, 48 gl::DrawElementsType type, 49 size_t offsetIn); 50 51 const gl::DrawElementsType type; 52 const size_t offset; 53 }; 54 55 class BufferHolderMtl 56 { 57 public: 58 virtual ~BufferHolderMtl() = default; 59 60 // Due to the complication of synchronizing accesses between CPU and GPU, 61 // a mtl::Buffer might be under used by GPU but CPU wants to modify its content through 62 // map() method, this could lead to GPU stalling. The more efficient method is maintain 63 // a queue of mtl::Buffer and only let CPU modifies a free mtl::Buffer. 64 // So, in order to let GPU use the most recent modified content, one must call this method 65 // right before the draw call to retrieved the most up-to-date mtl::Buffer. getCurrentBuffer()66 mtl::BufferRef getCurrentBuffer() { return mIsWeak ? mBufferWeakRef.lock() : mBuffer; } 67 68 protected: 69 mtl::BufferRef mBuffer; 70 mtl::BufferWeakRef mBufferWeakRef; 71 bool mIsWeak = false; 72 }; 73 74 class BufferMtl : public BufferImpl, public BufferHolderMtl 75 { 76 public: 77 BufferMtl(const gl::BufferState &state); 78 ~BufferMtl() override; 79 void destroy(const gl::Context *context) override; 80 81 angle::Result setData(const gl::Context *context, 82 gl::BufferBinding target, 83 const void *data, 84 size_t size, 85 gl::BufferUsage usage) override; 86 angle::Result setSubData(const gl::Context *context, 87 gl::BufferBinding target, 88 const void *data, 89 size_t size, 90 size_t offset) override; 91 angle::Result copySubData(const gl::Context *context, 92 BufferImpl *source, 93 GLintptr sourceOffset, 94 GLintptr destOffset, 95 GLsizeiptr size) override; 96 angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; 97 angle::Result mapRange(const gl::Context *context, 98 size_t offset, 99 size_t length, 100 GLbitfield access, 101 void **mapPtr) override; 102 angle::Result unmap(const gl::Context *context, GLboolean *result) override; 103 104 angle::Result getIndexRange(const gl::Context *context, 105 gl::DrawElementsType type, 106 size_t offset, 107 size_t count, 108 bool primitiveRestartEnabled, 109 gl::IndexRange *outRange) override; 110 111 angle::Result getFirstLastIndices(gl::DrawElementsType type, 112 size_t offset, 113 size_t count, 114 std::pair<uint32_t, uint32_t> *outIndices) const; 115 116 const uint8_t *getClientShadowCopyData(const gl::Context *context); 117 118 ConversionBufferMtl *getVertexConversionBuffer(const gl::Context *context, 119 angle::FormatID formatID, 120 GLuint stride, 121 size_t offset); 122 123 IndexConversionBufferMtl *getIndexConversionBuffer(const gl::Context *context, 124 gl::DrawElementsType type, 125 size_t offset); 126 size()127 size_t size() const { return static_cast<size_t>(mState.getSize()); } 128 129 private: 130 angle::Result setSubDataImpl(const gl::Context *context, 131 const void *data, 132 size_t size, 133 size_t offset); 134 135 angle::Result commitShadowCopy(const gl::Context *context); 136 angle::Result commitShadowCopy(const gl::Context *context, size_t size); 137 138 void markConversionBuffersDirty(); 139 140 void clearConversionBuffers(); 141 142 // Client side shadow buffer 143 angle::MemoryBuffer mShadowCopy; 144 145 // GPU side buffers pool 146 mtl::BufferPool mBufferPool; 147 148 struct VertexConversionBuffer : public ConversionBufferMtl 149 { 150 VertexConversionBuffer(const gl::Context *context, 151 angle::FormatID formatIDIn, 152 GLuint strideIn, 153 size_t offsetIn); 154 155 // The conversion is identified by the triple of {format, stride, offset}. 156 angle::FormatID formatID; 157 GLuint stride; 158 size_t offset; 159 }; 160 161 // A cache of converted vertex data. 162 std::vector<VertexConversionBuffer> mVertexConversionBuffers; 163 164 std::vector<IndexConversionBufferMtl> mIndexConversionBuffers; 165 }; 166 167 class SimpleWeakBufferHolderMtl : public BufferHolderMtl 168 { 169 public: 170 SimpleWeakBufferHolderMtl(); 171 set(const mtl::BufferRef & buffer)172 void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; } 173 }; 174 175 } // namespace rx 176 177 #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */ 178