xref: /aosp_15_r20/external/skia/src/gpu/graphite/BufferManager.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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