1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef skgpu_graphite_BufferManager_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_graphite_BufferManager_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/BufferWriter.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Buffer.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawTypes.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceTypes.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/UploadBufferManager.h" 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker #include <array> 20*c8dee2aaSAndroid Build Coastguard Worker #include <tuple> 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite { 23*c8dee2aaSAndroid Build Coastguard Worker 24*c8dee2aaSAndroid Build Coastguard Worker class Caps; 25*c8dee2aaSAndroid Build Coastguard Worker class Context; 26*c8dee2aaSAndroid Build Coastguard Worker class DrawBufferManager; 27*c8dee2aaSAndroid Build Coastguard Worker class GlobalCache; 28*c8dee2aaSAndroid Build Coastguard Worker class QueueManager; 29*c8dee2aaSAndroid Build Coastguard Worker class Recording; 30*c8dee2aaSAndroid Build Coastguard Worker class ResourceProvider; 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker /** 33*c8dee2aaSAndroid Build Coastguard Worker * ScratchBuffer represents a GPU buffer object that is allowed to be reused across strictly 34*c8dee2aaSAndroid Build Coastguard Worker * sequential tasks within a Recording. It can be used to sub-allocate multiple bindings. 35*c8dee2aaSAndroid Build Coastguard Worker * When a ScratchBuffer gets deallocated, the underlying GPU buffer gets returned to the 36*c8dee2aaSAndroid Build Coastguard Worker * originating DrawBufferManager for reuse. 37*c8dee2aaSAndroid Build Coastguard Worker */ 38*c8dee2aaSAndroid Build Coastguard Worker class ScratchBuffer final { 39*c8dee2aaSAndroid Build Coastguard Worker public: 40*c8dee2aaSAndroid Build Coastguard Worker // The default constructor creates an invalid ScratchBuffer that cannot be used for 41*c8dee2aaSAndroid Build Coastguard Worker // suballocations. 42*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer() = default; 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker // The destructor returns the underlying buffer back to the reuse pool, if the ScratchBuffer is 45*c8dee2aaSAndroid Build Coastguard Worker // valid. 46*c8dee2aaSAndroid Build Coastguard Worker ~ScratchBuffer(); 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker // Disallow copy 49*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer(const ScratchBuffer&) = delete; 50*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer& operator=(const ScratchBuffer&) = delete; 51*c8dee2aaSAndroid Build Coastguard Worker 52*c8dee2aaSAndroid Build Coastguard Worker // Allow move 53*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer(ScratchBuffer&&) = default; 54*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer& operator=(ScratchBuffer&&) = default; 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker // Returns false if the underlying buffer has been returned to the reuse pool. isValid()57*c8dee2aaSAndroid Build Coastguard Worker bool isValid() const { return static_cast<bool>(fBuffer); } 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker // Convenience wrapper for checking the validity of a buffer. 60*c8dee2aaSAndroid Build Coastguard Worker explicit operator bool() { return this->isValid(); } 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker // Logical size of the initially requested allocation. 63*c8dee2aaSAndroid Build Coastguard Worker // 64*c8dee2aaSAndroid Build Coastguard Worker // NOTE: This number may be different from the size of the underlying GPU buffer but it is 65*c8dee2aaSAndroid Build Coastguard Worker // guaranteed to be less than or equal to it. size()66*c8dee2aaSAndroid Build Coastguard Worker uint32_t size() const { return fSize; } 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker // Sub-allocate a slice within the scratch buffer object. Fails and returns a NULL pointer if 69*c8dee2aaSAndroid Build Coastguard Worker // the buffer doesn't have enough space remaining for `requiredBytes`. 70*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/330743233): Currently the suballocations use the alignment for the BufferInfo that was 71*c8dee2aaSAndroid Build Coastguard Worker // assigned by the DrawBufferManager based on the ScratchBuffer's buffer type. One way to 72*c8dee2aaSAndroid Build Coastguard Worker // generalize this across different buffer usages/types is to have this function accept an 73*c8dee2aaSAndroid Build Coastguard Worker // additional alignment parameter. That should happen after we loosen the coupling between 74*c8dee2aaSAndroid Build Coastguard Worker // DrawBufferManager's BufferInfos and ScratchBuffer reuse pools. 75*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo suballocate(size_t requiredBytes); 76*c8dee2aaSAndroid Build Coastguard Worker 77*c8dee2aaSAndroid Build Coastguard Worker // Returns the underlying buffer object back to the pool and invalidates this ScratchBuffer. 78*c8dee2aaSAndroid Build Coastguard Worker void returnToPool(); 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker private: 81*c8dee2aaSAndroid Build Coastguard Worker friend class DrawBufferManager; 82*c8dee2aaSAndroid Build Coastguard Worker 83*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer(uint32_t size, uint32_t alignment, sk_sp<Buffer>, DrawBufferManager*); 84*c8dee2aaSAndroid Build Coastguard Worker 85*c8dee2aaSAndroid Build Coastguard Worker uint32_t fSize; 86*c8dee2aaSAndroid Build Coastguard Worker uint32_t fAlignment; 87*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> fBuffer; 88*c8dee2aaSAndroid Build Coastguard Worker uint32_t fOffset = 0; 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Worker DrawBufferManager* fOwner = nullptr; 91*c8dee2aaSAndroid Build Coastguard Worker }; 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Worker /** 94*c8dee2aaSAndroid Build Coastguard Worker * DrawBufferManager controls writing to buffer data ranges within larger, cacheable Buffers and 95*c8dee2aaSAndroid Build Coastguard Worker * automatically handles either mapping or copying via transfer buffer depending on what the GPU 96*c8dee2aaSAndroid Build Coastguard Worker * hardware supports for the requested buffer type and use case. It is intended for repeatedly 97*c8dee2aaSAndroid Build Coastguard Worker * uploading dynamic data to the GPU. 98*c8dee2aaSAndroid Build Coastguard Worker */ 99*c8dee2aaSAndroid Build Coastguard Worker class DrawBufferManager { 100*c8dee2aaSAndroid Build Coastguard Worker public: 101*c8dee2aaSAndroid Build Coastguard Worker DrawBufferManager(ResourceProvider*, const Caps*, UploadBufferManager*); 102*c8dee2aaSAndroid Build Coastguard Worker ~DrawBufferManager(); 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker // Let possible users check if the manager is already in a bad mapping state and skip any extra 105*c8dee2aaSAndroid Build Coastguard Worker // work that will be wasted because the next Recording snap will fail. hasMappingFailed()106*c8dee2aaSAndroid Build Coastguard Worker bool hasMappingFailed() const { return fMappingFailed; } 107*c8dee2aaSAndroid Build Coastguard Worker 108*c8dee2aaSAndroid Build Coastguard Worker // These writers automatically calculate the required bytes based on count and stride. If a 109*c8dee2aaSAndroid Build Coastguard Worker // valid writer is returned, the byte count will fit in a uint32_t. 110*c8dee2aaSAndroid Build Coastguard Worker std::pair<VertexWriter, BindBufferInfo> getVertexWriter(size_t count, size_t stride); 111*c8dee2aaSAndroid Build Coastguard Worker std::pair<IndexWriter, BindBufferInfo> getIndexWriter(size_t count, size_t stride); 112*c8dee2aaSAndroid Build Coastguard Worker std::pair<UniformWriter, BindBufferInfo> getUniformWriter(size_t count, size_t stride); 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker // Return an SSBO writer that is aligned for binding, per the requirements in fCurrentBuffers. 115*c8dee2aaSAndroid Build Coastguard Worker std::pair<UniformWriter, BindBufferInfo> getSsboWriter(size_t count, size_t stride); 116*c8dee2aaSAndroid Build Coastguard Worker // Return an SSBO writer that is aligned for indexing from the shader, per the provided stride. 117*c8dee2aaSAndroid Build Coastguard Worker std::pair<UniformWriter, BindBufferInfo> getAlignedSsboWriter(size_t count, size_t stride); 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker // The remaining writers and buffer allocator functions assume that byte counts are safely 120*c8dee2aaSAndroid Build Coastguard Worker // calculated by the caller (e.g. Vello or ). 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker // Return a pointer to a mapped storage buffer suballocation without a specific data writer. 123*c8dee2aaSAndroid Build Coastguard Worker std::pair<void* /* mappedPtr */, BindBufferInfo> getUniformPointer(size_t requiredBytes); 124*c8dee2aaSAndroid Build Coastguard Worker std::pair<void* /* mappedPtr */, BindBufferInfo> getStoragePointer(size_t requiredBytes); 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Worker // Utilities that return an unmapped buffer suballocation for a particular usage. These buffers 127*c8dee2aaSAndroid Build Coastguard Worker // are intended to be only accessed by the GPU and are not intended for CPU data uploads. 128*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo getStorage(size_t requiredBytes, ClearBuffer cleared = ClearBuffer::kNo); 129*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo getVertexStorage(size_t requiredBytes); 130*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo getIndexStorage(size_t requiredBytes); 131*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo getIndirectStorage(size_t requiredBytes, ClearBuffer cleared = ClearBuffer::kNo); 132*c8dee2aaSAndroid Build Coastguard Worker 133*c8dee2aaSAndroid Build Coastguard Worker // Returns an entire storage buffer object that is large enough to fit `requiredBytes`. The 134*c8dee2aaSAndroid Build Coastguard Worker // returned ScratchBuffer can be used to sub-allocate one or more storage buffer bindings that 135*c8dee2aaSAndroid Build Coastguard Worker // reference the same buffer object. 136*c8dee2aaSAndroid Build Coastguard Worker // 137*c8dee2aaSAndroid Build Coastguard Worker // When the ScratchBuffer goes out of scope, the buffer object gets added to an internal pool 138*c8dee2aaSAndroid Build Coastguard Worker // and is available for immediate reuse. getScratchStorage() returns buffers from this pool if 139*c8dee2aaSAndroid Build Coastguard Worker // possible. A ScratchBuffer can be explicitly returned to the pool by calling `returnToPool()`. 140*c8dee2aaSAndroid Build Coastguard Worker // 141*c8dee2aaSAndroid Build Coastguard Worker // Returning a ScratchBuffer back to the buffer too early can result in validation failures 142*c8dee2aaSAndroid Build Coastguard Worker // and/or data races. It is the callers responsibility to manage reuse within a Recording and 143*c8dee2aaSAndroid Build Coastguard Worker // guarantee synchronized access to buffer bindings. 144*c8dee2aaSAndroid Build Coastguard Worker // 145*c8dee2aaSAndroid Build Coastguard Worker // This type of usage is currently limited to GPU-only storage buffers. 146*c8dee2aaSAndroid Build Coastguard Worker // 147*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/330743233): Generalize the underlying pool to other buffer types, including mapped 148*c8dee2aaSAndroid Build Coastguard Worker // ones. 149*c8dee2aaSAndroid Build Coastguard Worker ScratchBuffer getScratchStorage(size_t requiredBytes); 150*c8dee2aaSAndroid Build Coastguard Worker 151*c8dee2aaSAndroid Build Coastguard Worker // Returns the last 'unusedBytes' from the last call to getVertexWriter(). Assumes that 152*c8dee2aaSAndroid Build Coastguard Worker // 'unusedBytes' is less than the 'count*stride' to the original allocation. 153*c8dee2aaSAndroid Build Coastguard Worker void returnVertexBytes(size_t unusedBytes); 154*c8dee2aaSAndroid Build Coastguard Worker 155*c8dee2aaSAndroid Build Coastguard Worker // Finalizes all buffers and transfers ownership of them to a Recording. Returns true on success 156*c8dee2aaSAndroid Build Coastguard Worker // and false if a mapping had previously failed. 157*c8dee2aaSAndroid Build Coastguard Worker // 158*c8dee2aaSAndroid Build Coastguard Worker // Regardless of success or failure, the DrawBufferManager is reset to a valid initial state 159*c8dee2aaSAndroid Build Coastguard Worker // for recording buffer data for the next Recording. 160*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] bool transferToRecording(Recording*); 161*c8dee2aaSAndroid Build Coastguard Worker 162*c8dee2aaSAndroid Build Coastguard Worker private: 163*c8dee2aaSAndroid Build Coastguard Worker friend class ScratchBuffer; 164*c8dee2aaSAndroid Build Coastguard Worker 165*c8dee2aaSAndroid Build Coastguard Worker struct BufferInfo { 166*c8dee2aaSAndroid Build Coastguard Worker BufferInfo(BufferType type, uint32_t minBlockSize, uint32_t maxBlockSize, const Caps* caps); 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Worker const BufferType fType; 169*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fStartAlignment; 170*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fMinBlockSize; 171*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fMaxBlockSize; 172*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> fBuffer; 173*c8dee2aaSAndroid Build Coastguard Worker // The fTransferBuffer can be null, if draw buffer cannot be mapped, 174*c8dee2aaSAndroid Build Coastguard Worker // see Caps::drawBufferCanBeMapped() for detail. 175*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo fTransferBuffer{}; 176*c8dee2aaSAndroid Build Coastguard Worker void* fTransferMapPtr = nullptr; 177*c8dee2aaSAndroid Build Coastguard Worker uint32_t fOffset = 0; 178*c8dee2aaSAndroid Build Coastguard Worker 179*c8dee2aaSAndroid Build Coastguard Worker // Block size to use when creating new buffers; between fMinBlockSize and fMaxBlockSize. 180*c8dee2aaSAndroid Build Coastguard Worker uint32_t fCurBlockSize = 0; 181*c8dee2aaSAndroid Build Coastguard Worker // How many bytes have been used for for this buffer type since the last Recording snap. 182*c8dee2aaSAndroid Build Coastguard Worker uint32_t fUsedSize = 0; 183*c8dee2aaSAndroid Build Coastguard Worker }; 184*c8dee2aaSAndroid Build Coastguard Worker std::pair<void* /*mappedPtr*/, BindBufferInfo> prepareMappedBindBuffer( 185*c8dee2aaSAndroid Build Coastguard Worker BufferInfo* info, 186*c8dee2aaSAndroid Build Coastguard Worker std::string_view label, 187*c8dee2aaSAndroid Build Coastguard Worker uint32_t requiredBytes, 188*c8dee2aaSAndroid Build Coastguard Worker uint32_t requiredAlignment = 0); 189*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo prepareBindBuffer(BufferInfo* info, 190*c8dee2aaSAndroid Build Coastguard Worker std::string_view label, 191*c8dee2aaSAndroid Build Coastguard Worker uint32_t requiredBytes, 192*c8dee2aaSAndroid Build Coastguard Worker uint32_t requiredAlignment = 0, 193*c8dee2aaSAndroid Build Coastguard Worker bool supportCpuUpload = false, 194*c8dee2aaSAndroid Build Coastguard Worker ClearBuffer cleared = ClearBuffer::kNo); 195*c8dee2aaSAndroid Build Coastguard Worker 196*c8dee2aaSAndroid Build Coastguard Worker // Helper method for public getSsboWriter methods. 197*c8dee2aaSAndroid Build Coastguard Worker std::pair<UniformWriter, BindBufferInfo> getSsboWriter(size_t count, 198*c8dee2aaSAndroid Build Coastguard Worker size_t stride, 199*c8dee2aaSAndroid Build Coastguard Worker size_t alignment); 200*c8dee2aaSAndroid Build Coastguard Worker 201*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> findReusableSbo(size_t bufferSize); 202*c8dee2aaSAndroid Build Coastguard Worker 203*c8dee2aaSAndroid Build Coastguard Worker // Marks manager in a failed state, unmaps any previously collected buffers. 204*c8dee2aaSAndroid Build Coastguard Worker void onFailedBuffer(); 205*c8dee2aaSAndroid Build Coastguard Worker 206*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* const fResourceProvider; 207*c8dee2aaSAndroid Build Coastguard Worker const Caps* const fCaps; 208*c8dee2aaSAndroid Build Coastguard Worker UploadBufferManager* fUploadManager; 209*c8dee2aaSAndroid Build Coastguard Worker 210*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kVertexBufferIndex = 0; 211*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kIndexBufferIndex = 1; 212*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kUniformBufferIndex = 2; 213*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kStorageBufferIndex = 3; 214*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kGpuOnlyStorageBufferIndex = 4; 215*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kVertexStorageBufferIndex = 5; 216*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kIndexStorageBufferIndex = 6; 217*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kIndirectStorageBufferIndex = 7; 218*c8dee2aaSAndroid Build Coastguard Worker std::array<BufferInfo, 8> fCurrentBuffers; 219*c8dee2aaSAndroid Build Coastguard Worker 220*c8dee2aaSAndroid Build Coastguard Worker // Vector of buffer and transfer buffer pairs. 221*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<std::pair<sk_sp<Buffer>, BindBufferInfo>> fUsedBuffers; 222*c8dee2aaSAndroid Build Coastguard Worker 223*c8dee2aaSAndroid Build Coastguard Worker // List of buffer regions that were requested to be cleared at the time of allocation. 224*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<BindBufferInfo> fClearList; 225*c8dee2aaSAndroid Build Coastguard Worker 226*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/330744081): These should probably be maintained in a sorted data structure that 227*c8dee2aaSAndroid Build Coastguard Worker // supports fast insertion and lookup doesn't waste buffers (e.g. by vending out large buffers 228*c8dee2aaSAndroid Build Coastguard Worker // for small buffer sizes). 229*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/330743233): We may want this pool to contain buffers with mixed usages (such as 230*c8dee2aaSAndroid Build Coastguard Worker // VERTEX|INDEX|UNIFORM|STORAGE) to reduce buffer usage on platforms like Dawn where 231*c8dee2aaSAndroid Build Coastguard Worker // host-written data always go through a copy via transfer buffer. 232*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<sk_sp<Buffer>> fReusableScratchStorageBuffers; 233*c8dee2aaSAndroid Build Coastguard Worker 234*c8dee2aaSAndroid Build Coastguard Worker // If mapping failed on Buffers created/managed by this DrawBufferManager or by the mapped 235*c8dee2aaSAndroid Build Coastguard Worker // transfer buffers from the UploadManager, remember so that the next Recording will fail. 236*c8dee2aaSAndroid Build Coastguard Worker bool fMappingFailed = false; 237*c8dee2aaSAndroid Build Coastguard Worker }; 238*c8dee2aaSAndroid Build Coastguard Worker 239*c8dee2aaSAndroid Build Coastguard Worker /** 240*c8dee2aaSAndroid Build Coastguard Worker * The StaticBufferManager is the one-time-only analog to DrawBufferManager and provides "static" 241*c8dee2aaSAndroid Build Coastguard Worker * Buffers to RenderSteps and other Context-lifetime-tied objects, where the Buffers' contents will 242*c8dee2aaSAndroid Build Coastguard Worker * not change and can benefit from prioritizing GPU reads. The assumed use case is that they remain 243*c8dee2aaSAndroid Build Coastguard Worker * read-only on the GPU as well, so a single static buffer can be shared by all Recorders. 244*c8dee2aaSAndroid Build Coastguard Worker * 245*c8dee2aaSAndroid Build Coastguard Worker * Unlike DrawBufferManager's getXWriter() functions that return both a Writer and a BindBufferInfo, 246*c8dee2aaSAndroid Build Coastguard Worker * StaticBufferManager returns only a Writer and accepts a BindBufferInfo* as an argument. This will 247*c8dee2aaSAndroid Build Coastguard Worker * be re-written with the final binding info for the GPU-private data once that can be determined 248*c8dee2aaSAndroid Build Coastguard Worker * after *all* static buffers have been requested. 249*c8dee2aaSAndroid Build Coastguard Worker */ 250*c8dee2aaSAndroid Build Coastguard Worker class StaticBufferManager { 251*c8dee2aaSAndroid Build Coastguard Worker public: 252*c8dee2aaSAndroid Build Coastguard Worker StaticBufferManager(ResourceProvider*, const Caps*); 253*c8dee2aaSAndroid Build Coastguard Worker ~StaticBufferManager(); 254*c8dee2aaSAndroid Build Coastguard Worker 255*c8dee2aaSAndroid Build Coastguard Worker // The passed in BindBufferInfos are updated when finalize() is later called, to point to the 256*c8dee2aaSAndroid Build Coastguard Worker // packed, GPU-private buffer at the appropriate offset. The data written to the returned Writer 257*c8dee2aaSAndroid Build Coastguard Worker // is copied to the private buffer at that offset. 'binding' must live until finalize() returns. 258*c8dee2aaSAndroid Build Coastguard Worker VertexWriter getVertexWriter(size_t size, BindBufferInfo* binding); 259*c8dee2aaSAndroid Build Coastguard Worker // TODO: Update the tessellation index buffer generation functions to use an IndexWriter so this 260*c8dee2aaSAndroid Build Coastguard Worker // can return an IndexWriter vs. a VertexWriter that happens to just write uint16s... 261*c8dee2aaSAndroid Build Coastguard Worker VertexWriter getIndexWriter(size_t size, BindBufferInfo* binding); 262*c8dee2aaSAndroid Build Coastguard Worker 263*c8dee2aaSAndroid Build Coastguard Worker enum class FinishResult : int { 264*c8dee2aaSAndroid Build Coastguard Worker kFailure, // Unable to create or copy static buffers 265*c8dee2aaSAndroid Build Coastguard Worker kSuccess, // Successfully created static buffers and added GPU tasks to the queue 266*c8dee2aaSAndroid Build Coastguard Worker kNoWork // No static buffers required, no GPU tasks add to the queue 267*c8dee2aaSAndroid Build Coastguard Worker }; 268*c8dee2aaSAndroid Build Coastguard Worker 269*c8dee2aaSAndroid Build Coastguard Worker // Finalizes all buffers and records a copy task to compact and privatize static data. The 270*c8dee2aaSAndroid Build Coastguard Worker // final static buffers will become owned by the Context's GlobalCache. 271*c8dee2aaSAndroid Build Coastguard Worker FinishResult finalize(Context*, QueueManager*, GlobalCache*); 272*c8dee2aaSAndroid Build Coastguard Worker 273*c8dee2aaSAndroid Build Coastguard Worker private: 274*c8dee2aaSAndroid Build Coastguard Worker struct CopyRange { 275*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo fSource; // The CPU-to-GPU buffer and offset for the source of the copy 276*c8dee2aaSAndroid Build Coastguard Worker BindBufferInfo* fTarget; // The late-assigned destination of the copy 277*c8dee2aaSAndroid Build Coastguard Worker }; 278*c8dee2aaSAndroid Build Coastguard Worker struct BufferInfo { 279*c8dee2aaSAndroid Build Coastguard Worker BufferInfo(BufferType type, const Caps* caps); 280*c8dee2aaSAndroid Build Coastguard Worker 281*c8dee2aaSAndroid Build Coastguard Worker bool createAndUpdateBindings(ResourceProvider*, 282*c8dee2aaSAndroid Build Coastguard Worker Context*, 283*c8dee2aaSAndroid Build Coastguard Worker QueueManager*, 284*c8dee2aaSAndroid Build Coastguard Worker GlobalCache*, 285*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) const; resetBufferInfo286*c8dee2aaSAndroid Build Coastguard Worker void reset() { 287*c8dee2aaSAndroid Build Coastguard Worker fData.clear(); 288*c8dee2aaSAndroid Build Coastguard Worker fTotalRequiredBytes = 0; 289*c8dee2aaSAndroid Build Coastguard Worker } 290*c8dee2aaSAndroid Build Coastguard Worker 291*c8dee2aaSAndroid Build Coastguard Worker const BufferType fBufferType; 292*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fAlignment; 293*c8dee2aaSAndroid Build Coastguard Worker 294*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<CopyRange> fData; 295*c8dee2aaSAndroid Build Coastguard Worker uint32_t fTotalRequiredBytes; 296*c8dee2aaSAndroid Build Coastguard Worker }; 297*c8dee2aaSAndroid Build Coastguard Worker 298*c8dee2aaSAndroid Build Coastguard Worker void* prepareStaticData(BufferInfo* info, size_t requiredBytes, BindBufferInfo* target); 299*c8dee2aaSAndroid Build Coastguard Worker 300*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* const fResourceProvider; 301*c8dee2aaSAndroid Build Coastguard Worker UploadBufferManager fUploadManager; 302*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fRequiredTransferAlignment; 303*c8dee2aaSAndroid Build Coastguard Worker 304*c8dee2aaSAndroid Build Coastguard Worker // The source data that's copied into a final GPU-private buffer 305*c8dee2aaSAndroid Build Coastguard Worker BufferInfo fVertexBufferInfo; 306*c8dee2aaSAndroid Build Coastguard Worker BufferInfo fIndexBufferInfo; 307*c8dee2aaSAndroid Build Coastguard Worker 308*c8dee2aaSAndroid Build Coastguard Worker // If mapping failed on Buffers created/managed by this StaticBufferManager or by the mapped 309*c8dee2aaSAndroid Build Coastguard Worker // transfer buffers from the UploadManager, remember so that finalize() will fail. 310*c8dee2aaSAndroid Build Coastguard Worker bool fMappingFailed = false; 311*c8dee2aaSAndroid Build Coastguard Worker }; 312*c8dee2aaSAndroid Build Coastguard Worker 313*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite 314*c8dee2aaSAndroid Build Coastguard Worker 315*c8dee2aaSAndroid Build Coastguard Worker #endif // skgpu_graphite_BufferManager_DEFINED 316