xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrVertexChunkArray.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2021 Google LLC.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrVertexChunkArray_DEFINED
9 #define GrVertexChunkArray_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkTypes.h"
13 #include "include/private/base/SkDebug.h"
14 #include "include/private/base/SkNoncopyable.h"
15 #include "include/private/base/SkTArray.h"
16 #include "include/private/base/SkTypeTraits.h"
17 #include "src/gpu/BufferWriter.h"
18 #include "src/gpu/ganesh/GrBuffer.h"
19 
20 #include <cstddef>
21 #include <type_traits>
22 #include <utility>
23 
24 class GrMeshDrawTarget;
25 
26 // Represents a chunk of vertex data. Use with GrVertexChunkArray and GrVertexChunkBuilder. We write
27 // the data out in chunks when we don't start out knowing exactly how many vertices (or instances)
28 // we will end up writing.
29 struct GrVertexChunk {
30     sk_sp<const GrBuffer> fBuffer;
31     int fCount = 0;
32     int fBase;  // baseVertex or baseInstance, depending on the use case.
33 
34     static_assert(::sk_is_trivially_relocatable<decltype(fBuffer)>::value);
35 
36     using sk_is_trivially_relocatable = std::true_type;
37 };
38 
39 // Represents an array of GrVertexChunks.
40 //
41 // We only preallocate 1 chunk because if the array needs to grow, then we're also allocating a
42 // brand new GPU buffer anyway.
43 using GrVertexChunkArray = skia_private::STArray<1, GrVertexChunk>;
44 
45 // Builds a GrVertexChunkArray. The provided Target must not be used externally throughout the
46 // entire lifetime of this object.
47 class GrVertexChunkBuilder : SkNoncopyable {
48 public:
GrVertexChunkBuilder(GrMeshDrawTarget * target,GrVertexChunkArray * chunks,size_t stride,int minVerticesPerChunk)49     GrVertexChunkBuilder(GrMeshDrawTarget* target, GrVertexChunkArray* chunks,
50                          size_t stride, int minVerticesPerChunk)
51             : fTarget(target)
52             , fChunks(chunks)
53             , fStride(stride)
54             , fMinVerticesPerChunk(minVerticesPerChunk) {
55         SkASSERT(fMinVerticesPerChunk > 0);
56     }
57 
58     ~GrVertexChunkBuilder();
59 
stride()60     size_t stride() const { return fStride; }
61 
62     // Appends 'count' contiguous vertices. These vertices are not guaranteed to be contiguous with
63     // previous or future calls to appendVertices.
appendVertices(int count)64     SK_ALWAYS_INLINE skgpu::VertexWriter appendVertices(int count) {
65         SkASSERT(count > 0);
66         if (fCurrChunkVertexCount + count > fCurrChunkVertexCapacity && !this->allocChunk(count)) {
67             SkDEBUGCODE(fLastAppendAmount = 0;)
68             return {};
69         }
70         SkASSERT(fCurrChunkVertexCount + count <= fCurrChunkVertexCapacity);
71         fCurrChunkVertexCount += count;
72         SkDEBUGCODE(fLastAppendAmount = count;)
73         return std::exchange(fCurrChunkVertexWriter,
74                              fCurrChunkVertexWriter.makeOffset(fStride * count));
75     }
76 
77     // Pops the most recent 'count' contiguous vertices. Since there is no guarantee of contiguity
78     // between appends, 'count' may be no larger than the most recent call to appendVertices().
popVertices(int count)79     void popVertices(int count) {
80         SkASSERT(count <= fLastAppendAmount);
81         SkASSERT(fLastAppendAmount <= fCurrChunkVertexCount);
82         SkASSERT(count >= 0);
83         fCurrChunkVertexCount -= count;
84         fCurrChunkVertexWriter = fCurrChunkVertexWriter.makeOffset(fStride * -count);
85         SkDEBUGCODE(fLastAppendAmount -= count;)
86     }
87 
88 private:
89     bool allocChunk(int minCount);
90 
91     GrMeshDrawTarget* const fTarget;
92     GrVertexChunkArray* const fChunks;
93     const size_t fStride;
94     int fMinVerticesPerChunk;
95 
96     skgpu::VertexWriter fCurrChunkVertexWriter;
97     int fCurrChunkVertexCount = 0;
98     int fCurrChunkVertexCapacity = 0;
99 
100     SkDEBUGCODE(int fLastAppendAmount = 0;)
101 };
102 
103 #endif
104