1*8975f5c5SAndroid Build Coastguard Worker // 2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved. 3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker // 6*8975f5c5SAndroid Build Coastguard Worker // BufferMtl.h: 7*8975f5c5SAndroid Build Coastguard Worker // Defines the class interface for BufferMtl, implementing BufferImpl. 8*8975f5c5SAndroid Build Coastguard Worker // 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Worker #ifndef LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ 11*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Worker #import <Metal/Metal.h> 14*8975f5c5SAndroid Build Coastguard Worker 15*8975f5c5SAndroid Build Coastguard Worker #include <optional> 16*8975f5c5SAndroid Build Coastguard Worker #include <utility> 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h" 19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Observer.h" 20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h" 21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/BufferImpl.h" 22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/Format.h" 23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_buffer_pool.h" 24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_resources.h" 25*8975f5c5SAndroid Build Coastguard Worker 26*8975f5c5SAndroid Build Coastguard Worker namespace rx 27*8975f5c5SAndroid Build Coastguard Worker { 28*8975f5c5SAndroid Build Coastguard Worker 29*8975f5c5SAndroid Build Coastguard Worker struct DrawCommandRange 30*8975f5c5SAndroid Build Coastguard Worker { 31*8975f5c5SAndroid Build Coastguard Worker uint32_t count; 32*8975f5c5SAndroid Build Coastguard Worker size_t offset; 33*8975f5c5SAndroid Build Coastguard Worker }; 34*8975f5c5SAndroid Build Coastguard Worker 35*8975f5c5SAndroid Build Coastguard Worker // Inclusive range of consecutive primitive restart value indexes. 36*8975f5c5SAndroid Build Coastguard Worker struct IndexRange 37*8975f5c5SAndroid Build Coastguard Worker { IndexRangeIndexRange38*8975f5c5SAndroid Build Coastguard Worker IndexRange(size_t begin, size_t end) : restartBegin(begin), restartEnd(end) {} 39*8975f5c5SAndroid Build Coastguard Worker size_t restartBegin; 40*8975f5c5SAndroid Build Coastguard Worker size_t restartEnd; 41*8975f5c5SAndroid Build Coastguard Worker }; 42*8975f5c5SAndroid Build Coastguard Worker // Conversion buffers hold translated index and vertex data. 43*8975f5c5SAndroid Build Coastguard Worker struct ConversionBufferMtl 44*8975f5c5SAndroid Build Coastguard Worker { 45*8975f5c5SAndroid Build Coastguard Worker ConversionBufferMtl(ContextMtl *context, size_t initialSize, size_t alignment); 46*8975f5c5SAndroid Build Coastguard Worker ~ConversionBufferMtl(); 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker // One state value determines if we need to re-stream vertex data. 49*8975f5c5SAndroid Build Coastguard Worker bool dirty; 50*8975f5c5SAndroid Build Coastguard Worker 51*8975f5c5SAndroid Build Coastguard Worker // The conversion is stored in a dynamic buffer. 52*8975f5c5SAndroid Build Coastguard Worker mtl::BufferPool data; 53*8975f5c5SAndroid Build Coastguard Worker // These properties are to be filled by user of this buffer conversion 54*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef convertedBuffer; 55*8975f5c5SAndroid Build Coastguard Worker size_t convertedOffset; 56*8975f5c5SAndroid Build Coastguard Worker }; 57*8975f5c5SAndroid Build Coastguard Worker 58*8975f5c5SAndroid Build Coastguard Worker struct VertexConversionBufferMtl : public ConversionBufferMtl 59*8975f5c5SAndroid Build Coastguard Worker { 60*8975f5c5SAndroid Build Coastguard Worker VertexConversionBufferMtl(ContextMtl *context, 61*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatIDIn, 62*8975f5c5SAndroid Build Coastguard Worker GLuint strideIn, 63*8975f5c5SAndroid Build Coastguard Worker size_t offsetIn); 64*8975f5c5SAndroid Build Coastguard Worker 65*8975f5c5SAndroid Build Coastguard Worker // The conversion is identified by the triple of {format, stride, offset}. 66*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatID; 67*8975f5c5SAndroid Build Coastguard Worker GLuint stride; 68*8975f5c5SAndroid Build Coastguard Worker size_t offset; 69*8975f5c5SAndroid Build Coastguard Worker }; 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker struct IndexConversionBufferMtl : public ConversionBufferMtl 72*8975f5c5SAndroid Build Coastguard Worker { 73*8975f5c5SAndroid Build Coastguard Worker IndexConversionBufferMtl(ContextMtl *context, 74*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType elemType, 75*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartEnabled, 76*8975f5c5SAndroid Build Coastguard Worker size_t offsetIn); 77*8975f5c5SAndroid Build Coastguard Worker const gl::DrawElementsType elemType; 78*8975f5c5SAndroid Build Coastguard Worker const size_t offset; 79*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartEnabled; 80*8975f5c5SAndroid Build Coastguard Worker IndexRange getRangeForConvertedBuffer(size_t count); 81*8975f5c5SAndroid Build Coastguard Worker }; 82*8975f5c5SAndroid Build Coastguard Worker 83*8975f5c5SAndroid Build Coastguard Worker struct UniformConversionBufferMtl : public ConversionBufferMtl 84*8975f5c5SAndroid Build Coastguard Worker { 85*8975f5c5SAndroid Build Coastguard Worker UniformConversionBufferMtl(ContextMtl *context, 86*8975f5c5SAndroid Build Coastguard Worker std::pair<size_t, size_t> offsetIn, 87*8975f5c5SAndroid Build Coastguard Worker size_t blockSize); 88*8975f5c5SAndroid Build Coastguard Worker initialSrcOffsetUniformConversionBufferMtl89*8975f5c5SAndroid Build Coastguard Worker size_t initialSrcOffset() { return offset.second; } 90*8975f5c5SAndroid Build Coastguard Worker 91*8975f5c5SAndroid Build Coastguard Worker const size_t uniformBufferBlockSize; 92*8975f5c5SAndroid Build Coastguard Worker const std::pair<size_t, size_t> offset; 93*8975f5c5SAndroid Build Coastguard Worker }; 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker class BufferHolderMtl 96*8975f5c5SAndroid Build Coastguard Worker { 97*8975f5c5SAndroid Build Coastguard Worker public: 98*8975f5c5SAndroid Build Coastguard Worker virtual ~BufferHolderMtl() = default; 99*8975f5c5SAndroid Build Coastguard Worker 100*8975f5c5SAndroid Build Coastguard Worker // Due to the complication of synchronizing accesses between CPU and GPU, 101*8975f5c5SAndroid Build Coastguard Worker // a mtl::Buffer might be under used by GPU but CPU wants to modify its content through 102*8975f5c5SAndroid Build Coastguard Worker // map() method, this could lead to GPU stalling. The more efficient method is maintain 103*8975f5c5SAndroid Build Coastguard Worker // a queue of mtl::Buffer and only let CPU modifies a free mtl::Buffer. 104*8975f5c5SAndroid Build Coastguard Worker // So, in order to let GPU use the most recent modified content, one must call this method 105*8975f5c5SAndroid Build Coastguard Worker // right before the draw call to retrieved the most up-to-date mtl::Buffer. getCurrentBuffer()106*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef getCurrentBuffer() const { return mIsWeak ? mBufferWeakRef.lock() : mBuffer; } 107*8975f5c5SAndroid Build Coastguard Worker 108*8975f5c5SAndroid Build Coastguard Worker protected: 109*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef mBuffer; 110*8975f5c5SAndroid Build Coastguard Worker mtl::BufferWeakRef mBufferWeakRef; 111*8975f5c5SAndroid Build Coastguard Worker bool mIsWeak = false; 112*8975f5c5SAndroid Build Coastguard Worker }; 113*8975f5c5SAndroid Build Coastguard Worker 114*8975f5c5SAndroid Build Coastguard Worker class BufferMtl : public BufferImpl, public BufferHolderMtl 115*8975f5c5SAndroid Build Coastguard Worker { 116*8975f5c5SAndroid Build Coastguard Worker public: 117*8975f5c5SAndroid Build Coastguard Worker BufferMtl(const gl::BufferState &state); 118*8975f5c5SAndroid Build Coastguard Worker ~BufferMtl() override; 119*8975f5c5SAndroid Build Coastguard Worker void destroy(const gl::Context *context) override; 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker angle::Result setData(const gl::Context *context, 122*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target, 123*8975f5c5SAndroid Build Coastguard Worker const void *data, 124*8975f5c5SAndroid Build Coastguard Worker size_t size, 125*8975f5c5SAndroid Build Coastguard Worker gl::BufferUsage usage) override; 126*8975f5c5SAndroid Build Coastguard Worker angle::Result setSubData(const gl::Context *context, 127*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target, 128*8975f5c5SAndroid Build Coastguard Worker const void *data, 129*8975f5c5SAndroid Build Coastguard Worker size_t size, 130*8975f5c5SAndroid Build Coastguard Worker size_t offset) override; 131*8975f5c5SAndroid Build Coastguard Worker angle::Result copySubData(const gl::Context *context, 132*8975f5c5SAndroid Build Coastguard Worker BufferImpl *source, 133*8975f5c5SAndroid Build Coastguard Worker GLintptr sourceOffset, 134*8975f5c5SAndroid Build Coastguard Worker GLintptr destOffset, 135*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size) override; 136*8975f5c5SAndroid Build Coastguard Worker angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; 137*8975f5c5SAndroid Build Coastguard Worker angle::Result mapRange(const gl::Context *context, 138*8975f5c5SAndroid Build Coastguard Worker size_t offset, 139*8975f5c5SAndroid Build Coastguard Worker size_t length, 140*8975f5c5SAndroid Build Coastguard Worker GLbitfield access, 141*8975f5c5SAndroid Build Coastguard Worker void **mapPtr) override; 142*8975f5c5SAndroid Build Coastguard Worker angle::Result unmap(const gl::Context *context, GLboolean *result) override; 143*8975f5c5SAndroid Build Coastguard Worker 144*8975f5c5SAndroid Build Coastguard Worker angle::Result getIndexRange(const gl::Context *context, 145*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 146*8975f5c5SAndroid Build Coastguard Worker size_t offset, 147*8975f5c5SAndroid Build Coastguard Worker size_t count, 148*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartEnabled, 149*8975f5c5SAndroid Build Coastguard Worker gl::IndexRange *outRange) override; 150*8975f5c5SAndroid Build Coastguard Worker 151*8975f5c5SAndroid Build Coastguard Worker void onDataChanged() override; 152*8975f5c5SAndroid Build Coastguard Worker 153*8975f5c5SAndroid Build Coastguard Worker angle::Result getFirstLastIndices(ContextMtl *contextMtl, 154*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 155*8975f5c5SAndroid Build Coastguard Worker size_t offset, 156*8975f5c5SAndroid Build Coastguard Worker size_t count, 157*8975f5c5SAndroid Build Coastguard Worker std::pair<uint32_t, uint32_t> *outIndices); 158*8975f5c5SAndroid Build Coastguard Worker 159*8975f5c5SAndroid Build Coastguard Worker const uint8_t *getBufferDataReadOnly(ContextMtl *contextMtl); 160*8975f5c5SAndroid Build Coastguard Worker bool isSafeToReadFromBufferViaBlit(ContextMtl *contextMtl); 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker ConversionBufferMtl *getVertexConversionBuffer(ContextMtl *context, 163*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatID, 164*8975f5c5SAndroid Build Coastguard Worker GLuint stride, 165*8975f5c5SAndroid Build Coastguard Worker size_t offset); 166*8975f5c5SAndroid Build Coastguard Worker 167*8975f5c5SAndroid Build Coastguard Worker IndexConversionBufferMtl *getIndexConversionBuffer(ContextMtl *context, 168*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType elemType, 169*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartEnabled, 170*8975f5c5SAndroid Build Coastguard Worker size_t offset); 171*8975f5c5SAndroid Build Coastguard Worker 172*8975f5c5SAndroid Build Coastguard Worker ConversionBufferMtl *getUniformConversionBuffer(ContextMtl *context, 173*8975f5c5SAndroid Build Coastguard Worker std::pair<size_t, size_t> offset, 174*8975f5c5SAndroid Build Coastguard Worker size_t blockSize); 175*8975f5c5SAndroid Build Coastguard Worker size()176*8975f5c5SAndroid Build Coastguard Worker size_t size() const { return static_cast<size_t>(mState.getSize()); } 177*8975f5c5SAndroid Build Coastguard Worker 178*8975f5c5SAndroid Build Coastguard Worker const std::vector<IndexRange> &getRestartIndices(ContextMtl *ctx, 179*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType indexType); 180*8975f5c5SAndroid Build Coastguard Worker 181*8975f5c5SAndroid Build Coastguard Worker static const std::vector<IndexRange> getRestartIndicesFromClientData( 182*8975f5c5SAndroid Build Coastguard Worker ContextMtl *ctx, 183*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType indexType, 184*8975f5c5SAndroid Build Coastguard Worker const mtl::BufferRef clientBuffer); 185*8975f5c5SAndroid Build Coastguard Worker 186*8975f5c5SAndroid Build Coastguard Worker private: 187*8975f5c5SAndroid Build Coastguard Worker angle::Result allocateNewMetalBuffer(ContextMtl *contextMtl, 188*8975f5c5SAndroid Build Coastguard Worker MTLStorageMode storageMode, 189*8975f5c5SAndroid Build Coastguard Worker size_t size, 190*8975f5c5SAndroid Build Coastguard Worker bool returnOldBufferImmediately); 191*8975f5c5SAndroid Build Coastguard Worker 192*8975f5c5SAndroid Build Coastguard Worker angle::Result setDataImpl(const gl::Context *context, 193*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target, 194*8975f5c5SAndroid Build Coastguard Worker const void *data, 195*8975f5c5SAndroid Build Coastguard Worker size_t size, 196*8975f5c5SAndroid Build Coastguard Worker gl::BufferUsage usage); 197*8975f5c5SAndroid Build Coastguard Worker angle::Result setSubDataImpl(const gl::Context *context, 198*8975f5c5SAndroid Build Coastguard Worker const void *data, 199*8975f5c5SAndroid Build Coastguard Worker size_t size, 200*8975f5c5SAndroid Build Coastguard Worker size_t offset); 201*8975f5c5SAndroid Build Coastguard Worker 202*8975f5c5SAndroid Build Coastguard Worker angle::Result commitShadowCopy(ContextMtl *contextMtl); 203*8975f5c5SAndroid Build Coastguard Worker angle::Result commitShadowCopy(ContextMtl *contextMtl, size_t size); 204*8975f5c5SAndroid Build Coastguard Worker 205*8975f5c5SAndroid Build Coastguard Worker void markConversionBuffersDirty(); 206*8975f5c5SAndroid Build Coastguard Worker void clearConversionBuffers(); 207*8975f5c5SAndroid Build Coastguard Worker 208*8975f5c5SAndroid Build Coastguard Worker angle::Result putDataInNewBufferAndStartUsingNewBuffer(ContextMtl *contextMtl, 209*8975f5c5SAndroid Build Coastguard Worker const uint8_t *srcPtr, 210*8975f5c5SAndroid Build Coastguard Worker size_t sizeToCopy, 211*8975f5c5SAndroid Build Coastguard Worker size_t offset); 212*8975f5c5SAndroid Build Coastguard Worker angle::Result updateExistingBufferViaBlitFromStagingBuffer(ContextMtl *contextMtl, 213*8975f5c5SAndroid Build Coastguard Worker const uint8_t *srcPtr, 214*8975f5c5SAndroid Build Coastguard Worker size_t sizeToCopy, 215*8975f5c5SAndroid Build Coastguard Worker size_t offset); 216*8975f5c5SAndroid Build Coastguard Worker angle::Result copyDataToExistingBufferViaCPU(ContextMtl *contextMtl, 217*8975f5c5SAndroid Build Coastguard Worker const uint8_t *srcPtr, 218*8975f5c5SAndroid Build Coastguard Worker size_t sizeToCopy, 219*8975f5c5SAndroid Build Coastguard Worker size_t offset); 220*8975f5c5SAndroid Build Coastguard Worker angle::Result updateShadowCopyThenCopyShadowToNewBuffer(ContextMtl *contextMtl, 221*8975f5c5SAndroid Build Coastguard Worker const uint8_t *srcPtr, 222*8975f5c5SAndroid Build Coastguard Worker size_t sizeToCopy, 223*8975f5c5SAndroid Build Coastguard Worker size_t offset); 224*8975f5c5SAndroid Build Coastguard Worker 225*8975f5c5SAndroid Build Coastguard Worker bool clientShadowCopyDataNeedSync(ContextMtl *contextMtl); 226*8975f5c5SAndroid Build Coastguard Worker void ensureShadowCopySyncedFromGPU(ContextMtl *contextMtl); 227*8975f5c5SAndroid Build Coastguard Worker uint8_t *syncAndObtainShadowCopy(ContextMtl *contextMtl); 228*8975f5c5SAndroid Build Coastguard Worker 229*8975f5c5SAndroid Build Coastguard Worker // Optional client side shadow buffer 230*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer mShadowCopy; 231*8975f5c5SAndroid Build Coastguard Worker 232*8975f5c5SAndroid Build Coastguard Worker // A cache of converted vertex data. 233*8975f5c5SAndroid Build Coastguard Worker std::vector<VertexConversionBufferMtl> mVertexConversionBuffers; 234*8975f5c5SAndroid Build Coastguard Worker 235*8975f5c5SAndroid Build Coastguard Worker std::vector<IndexConversionBufferMtl> mIndexConversionBuffers; 236*8975f5c5SAndroid Build Coastguard Worker 237*8975f5c5SAndroid Build Coastguard Worker std::vector<UniformConversionBufferMtl> mUniformConversionBuffers; 238*8975f5c5SAndroid Build Coastguard Worker 239*8975f5c5SAndroid Build Coastguard Worker struct RestartRangeCache 240*8975f5c5SAndroid Build Coastguard Worker { RestartRangeCacheRestartRangeCache241*8975f5c5SAndroid Build Coastguard Worker RestartRangeCache(std::vector<IndexRange> &&ranges_, gl::DrawElementsType indexType_) 242*8975f5c5SAndroid Build Coastguard Worker : ranges(ranges_), indexType(indexType_) 243*8975f5c5SAndroid Build Coastguard Worker {} 244*8975f5c5SAndroid Build Coastguard Worker const std::vector<IndexRange> ranges; 245*8975f5c5SAndroid Build Coastguard Worker const gl::DrawElementsType indexType; 246*8975f5c5SAndroid Build Coastguard Worker }; 247*8975f5c5SAndroid Build Coastguard Worker std::optional<RestartRangeCache> mRestartRangeCache; 248*8975f5c5SAndroid Build Coastguard Worker std::vector<IndexRange> mRestartIndices; 249*8975f5c5SAndroid Build Coastguard Worker size_t mGLSize = 0; // size GL asked for (vs size we actually allocated) 250*8975f5c5SAndroid Build Coastguard Worker size_t mRevisionCount = 0; // for generating labels only 251*8975f5c5SAndroid Build Coastguard Worker gl::BufferUsage mUsage; 252*8975f5c5SAndroid Build Coastguard Worker }; 253*8975f5c5SAndroid Build Coastguard Worker 254*8975f5c5SAndroid Build Coastguard Worker class SimpleWeakBufferHolderMtl : public BufferHolderMtl 255*8975f5c5SAndroid Build Coastguard Worker { 256*8975f5c5SAndroid Build Coastguard Worker public: 257*8975f5c5SAndroid Build Coastguard Worker SimpleWeakBufferHolderMtl(); 258*8975f5c5SAndroid Build Coastguard Worker set(const mtl::BufferRef & buffer)259*8975f5c5SAndroid Build Coastguard Worker void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; } 260*8975f5c5SAndroid Build Coastguard Worker }; 261*8975f5c5SAndroid Build Coastguard Worker 262*8975f5c5SAndroid Build Coastguard Worker } // namespace rx 263*8975f5c5SAndroid Build Coastguard Worker 264*8975f5c5SAndroid Build Coastguard Worker #endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */ 265