• 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/private/SkNoncopyable.h"
12 #include "include/private/SkTArray.h"
13 #include "src/gpu/GrBuffer.h"
14 #include "src/gpu/GrVertexWriter.h"
15 #include "src/gpu/ops/GrMeshDrawOp.h"
16 
17 // Represents a chunk of vertex data. Use with GrVertexChunkArray and GrVertexChunkBuilder. We write
18 // the data out in chunks when we don't start out knowing exactly how many vertices (or instances)
19 // we will end up writing.
20 struct GrVertexChunk {
21     sk_sp<const GrBuffer> fBuffer;
22     int fCount = 0;
23     int fBase;  // baseVertex or baseInstance, depending on the use case.
24 };
25 
26 // Represents an array of GrVertexChunks.
27 //
28 // We only preallocate 1 chunk because if the array needs to grow, then we're also allocating a
29 // brand new GPU buffer anyway.
30 using GrVertexChunkArray = SkSTArray<1, GrVertexChunk>;
31 
32 // Builds a GrVertexChunkArray. The provided Target must not be used externally throughout the
33 // entire lifetime of this object.
34 class GrVertexChunkBuilder : SkNoncopyable {
35 public:
GrVertexChunkBuilder(GrMeshDrawOp::Target * target,GrVertexChunkArray * chunks,size_t stride,int minVerticesPerChunk)36     GrVertexChunkBuilder(GrMeshDrawOp::Target* target, GrVertexChunkArray* chunks, size_t stride,
37                          int minVerticesPerChunk)
38             : fTarget(target)
39             , fChunks(chunks)
40             , fStride(stride)
41             , fMinVerticesPerChunk(minVerticesPerChunk) {
42         SkASSERT(fMinVerticesPerChunk > 0);
43     }
44 
~GrVertexChunkBuilder()45     ~GrVertexChunkBuilder() {
46         if (!fChunks->empty()) {
47             fTarget->putBackVertices(fCurrChunkVertexCapacity - fCurrChunkVertexCount, fStride);
48             fChunks->back().fCount = fCurrChunkVertexCount;
49         }
50     }
51 
52     // Appends 'count' contiguous vertices. These vertices are not guaranteed to be contiguous with
53     // previous or future calls to appendVertices.
appendVertices(int count)54     SK_ALWAYS_INLINE GrVertexWriter appendVertices(int count) {
55         SkASSERT(count > 0);
56         if (fCurrChunkVertexCount + count > fCurrChunkVertexCapacity && !this->allocChunk(count)) {
57             return {nullptr};
58         }
59         SkASSERT(fCurrChunkVertexCount + count <= fCurrChunkVertexCapacity);
60         fCurrChunkVertexCount += count;
61         return std::exchange(fCurrChunkVertexWriter,
62                              fCurrChunkVertexWriter.makeOffset(fStride * count));
63     }
64 
appendVertex()65     SK_ALWAYS_INLINE GrVertexWriter appendVertex() { return this->appendVertices(1); }
66 
67 private:
allocChunk(int minCount)68     bool allocChunk(int minCount) {
69         if (!fChunks->empty()) {
70             // No need to put back vertices; the buffer is full.
71             fChunks->back().fCount = fCurrChunkVertexCount;
72         }
73         fCurrChunkVertexCount = 0;
74         GrVertexChunk* chunk = &fChunks->push_back();
75         fCurrChunkVertexWriter = {fTarget->makeVertexSpaceAtLeast(fStride,
76                                                                   fMinVerticesPerChunk * minCount,
77                                                                   fMinVerticesPerChunk * minCount,
78                                                                   &chunk->fBuffer,
79                                                                   &chunk->fBase,
80                                                                   &fCurrChunkVertexCapacity)};
81         if (!fCurrChunkVertexWriter || !chunk->fBuffer || fCurrChunkVertexCapacity < minCount) {
82             SkDebugf("WARNING: Failed to allocate vertex buffer for GrVertexChunk.\n");
83             fChunks->pop_back();
84             SkASSERT(fCurrChunkVertexCount == 0);
85             fCurrChunkVertexCapacity = 0;
86             return false;
87         }
88         fMinVerticesPerChunk *= 2;
89         return true;
90     }
91 
92     GrMeshDrawOp::Target* const fTarget;
93     GrVertexChunkArray* const fChunks;
94     const size_t fStride;
95     size_t fMinVerticesPerChunk;
96 
97     GrVertexWriter fCurrChunkVertexWriter;
98     int fCurrChunkVertexCount = 0;
99     int fCurrChunkVertexCapacity = 0;
100 };
101 
102 #endif
103