• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/private/SkNoncopyable.h"
13 #include "include/private/SkTArray.h"
14 #include "src/gpu/BufferWriter.h"
15 #include "src/gpu/GrBuffer.h"
16 
17 class GrMeshDrawTarget;
18 
19 // Represents a chunk of vertex data. Use with GrVertexChunkArray and GrVertexChunkBuilder. We write
20 // the data out in chunks when we don't start out knowing exactly how many vertices (or instances)
21 // we will end up writing.
22 struct GrVertexChunk {
23     sk_sp<const GrBuffer> fBuffer;
24     int fCount = 0;
25     int fBase;  // baseVertex or baseInstance, depending on the use case.
26 };
27 
28 // Represents an array of GrVertexChunks.
29 //
30 // We only preallocate 1 chunk because if the array needs to grow, then we're also allocating a
31 // brand new GPU buffer anyway.
32 using GrVertexChunkArray = SkSTArray<1, GrVertexChunk>;
33 
34 // Builds a GrVertexChunkArray. The provided Target must not be used externally throughout the
35 // entire lifetime of this object.
36 class GrVertexChunkBuilder : SkNoncopyable {
37 public:
GrVertexChunkBuilder(GrMeshDrawTarget * target,GrVertexChunkArray * chunks,size_t stride,int minVerticesPerChunk)38     GrVertexChunkBuilder(GrMeshDrawTarget* target, GrVertexChunkArray* chunks, size_t stride,
39                          int minVerticesPerChunk)
40             : fTarget(target)
41             , fChunks(chunks)
42             , fStride(stride)
43             , fMinVerticesPerChunk(minVerticesPerChunk) {
44         SkASSERT(fMinVerticesPerChunk > 0);
45     }
46 
47     ~GrVertexChunkBuilder();
48 
stride()49     size_t stride() const { return fStride; }
50 
51     // Appends 'count' contiguous vertices. These vertices are not guaranteed to be contiguous with
52     // previous or future calls to appendVertices.
appendVertices(int count)53     SK_ALWAYS_INLINE skgpu::VertexWriter appendVertices(int count) {
54         SkASSERT(count > 0);
55         if (fCurrChunkVertexCount + count > fCurrChunkVertexCapacity && !this->allocChunk(count)) {
56             SkDEBUGCODE(fLastAppendAmount = 0;)
57             return {nullptr};
58         }
59         SkASSERT(fCurrChunkVertexCount + count <= fCurrChunkVertexCapacity);
60         fCurrChunkVertexCount += count;
61         SkDEBUGCODE(fLastAppendAmount = count;)
62         return std::exchange(fCurrChunkVertexWriter,
63                              fCurrChunkVertexWriter.makeOffset(fStride * count));
64     }
65 
appendVertex()66     SK_ALWAYS_INLINE skgpu::VertexWriter appendVertex() { return this->appendVertices(1); }
67 
68     // Pops the most recent 'count' contiguous vertices. Since there is no guarantee of contiguity
69     // between appends, 'count' may be no larger than the most recent call to appendVertices().
popVertices(int count)70     void popVertices(int count) {
71         SkASSERT(count <= fLastAppendAmount);
72         SkASSERT(fLastAppendAmount <= fCurrChunkVertexCount);
73         SkASSERT(count >= 0);
74         fCurrChunkVertexCount -= count;
75         fCurrChunkVertexWriter = fCurrChunkVertexWriter.makeOffset(fStride * -count);
76         SkDEBUGCODE(fLastAppendAmount -= count;)
77     }
78 
79 private:
80     bool allocChunk(int minCount);
81 
82     GrMeshDrawTarget* const fTarget;
83     GrVertexChunkArray* const fChunks;
84     const size_t fStride;
85     int fMinVerticesPerChunk;
86 
87     skgpu::VertexWriter fCurrChunkVertexWriter;
88     int fCurrChunkVertexCount = 0;
89     int fCurrChunkVertexCapacity = 0;
90 
91     SkDEBUGCODE(int fLastAppendAmount = 0;)
92 };
93 
94 #endif
95