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(const gl::Context * context)66 mtl::BufferRef getCurrentBuffer(const gl::Context *context) 67 { 68 return mIsWeak ? mBufferWeakRef.lock() : mBuffer; 69 } 70 71 protected: 72 mtl::BufferRef mBuffer; 73 mtl::BufferWeakRef mBufferWeakRef; 74 bool mIsWeak = false; 75 }; 76 77 class BufferMtl : public BufferImpl, public BufferHolderMtl 78 { 79 public: 80 BufferMtl(const gl::BufferState &state); 81 ~BufferMtl() override; 82 void destroy(const gl::Context *context) override; 83 84 angle::Result setData(const gl::Context *context, 85 gl::BufferBinding target, 86 const void *data, 87 size_t size, 88 gl::BufferUsage usage) override; 89 angle::Result setSubData(const gl::Context *context, 90 gl::BufferBinding target, 91 const void *data, 92 size_t size, 93 size_t offset) override; 94 angle::Result copySubData(const gl::Context *context, 95 BufferImpl *source, 96 GLintptr sourceOffset, 97 GLintptr destOffset, 98 GLsizeiptr size) override; 99 angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; 100 angle::Result mapRange(const gl::Context *context, 101 size_t offset, 102 size_t length, 103 GLbitfield access, 104 void **mapPtr) override; 105 angle::Result unmap(const gl::Context *context, GLboolean *result) override; 106 107 angle::Result getIndexRange(const gl::Context *context, 108 gl::DrawElementsType type, 109 size_t offset, 110 size_t count, 111 bool primitiveRestartEnabled, 112 gl::IndexRange *outRange) override; 113 114 angle::Result getFirstLastIndices(const gl::Context *context, 115 gl::DrawElementsType type, 116 size_t offset, 117 size_t count, 118 std::pair<uint32_t, uint32_t> *outIndices) const; 119 120 const uint8_t *getClientShadowCopyData(const gl::Context *context); 121 122 ConversionBufferMtl *getVertexConversionBuffer(const gl::Context *context, 123 angle::FormatID formatID, 124 GLuint stride, 125 size_t offset); 126 127 IndexConversionBufferMtl *getIndexConversionBuffer(const gl::Context *context, 128 gl::DrawElementsType type, 129 size_t offset); 130 size()131 size_t size() const { return static_cast<size_t>(mState.getSize()); } 132 133 private: 134 angle::Result setSubDataImpl(const gl::Context *context, 135 const void *data, 136 size_t size, 137 size_t offset); 138 139 angle::Result commitShadowCopy(const gl::Context *context); 140 angle::Result commitShadowCopy(const gl::Context *context, size_t size); 141 142 void markConversionBuffersDirty(); 143 144 void clearConversionBuffers(); 145 146 // Client side shadow buffer 147 angle::MemoryBuffer mShadowCopy; 148 149 // GPU side buffers pool 150 mtl::BufferPool mBufferPool; 151 152 struct VertexConversionBuffer : public ConversionBufferMtl 153 { 154 VertexConversionBuffer(const gl::Context *context, 155 angle::FormatID formatIDIn, 156 GLuint strideIn, 157 size_t offsetIn); 158 159 // The conversion is identified by the triple of {format, stride, offset}. 160 angle::FormatID formatID; 161 GLuint stride; 162 size_t offset; 163 }; 164 165 // A cache of converted vertex data. 166 std::vector<VertexConversionBuffer> mVertexConversionBuffers; 167 168 std::vector<IndexConversionBufferMtl> mIndexConversionBuffers; 169 }; 170 171 class SimpleWeakBufferHolderMtl : public BufferHolderMtl 172 { 173 public: 174 SimpleWeakBufferHolderMtl(); 175 set(const mtl::BufferRef & buffer)176 void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; } 177 }; 178 179 } // namespace rx 180 181 #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */ 182