• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google Inc.
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 GrEagerVertexAllocator_DEFINED
9 #define GrEagerVertexAllocator_DEFINED
10 
11 #include "src/gpu/GrThreadSafeCache.h"
12 #include "src/gpu/ops/GrMeshDrawOp.h"
13 
14 // This interface is used to allocate and map GPU vertex data before the exact number of required
15 // vertices is known. Usage pattern:
16 //
17 //   1. Call lock(eagerCount) with an upper bound on the number of required vertices.
18 //   2. Compute and write vertex data to the returned pointer (if not null).
19 //   3. Call unlock(actualCount) and provide the actual number of vertices written during step #2.
20 //
21 // On step #3, the implementation will attempt to shrink the underlying GPU memory slot to fit the
22 // actual vertex count.
23 class GrEagerVertexAllocator {
24 public:
lock(int eagerCount)25     template<typename T> T* lock(int eagerCount) {
26         return static_cast<T*>(this->lock(sizeof(T), eagerCount));
27     }
28     virtual void* lock(size_t stride, int eagerCount) = 0;
29 
30     virtual void unlock(int actualCount) = 0;
31 
~GrEagerVertexAllocator()32     virtual ~GrEagerVertexAllocator() {}
33 };
34 
35 // GrEagerVertexAllocator implementation that uses GrMeshDrawOp::Target::makeVertexSpace and
36 // GrMeshDrawOp::Target::putBackVertices.
37 class GrEagerDynamicVertexAllocator : public GrEagerVertexAllocator {
38 public:
GrEagerDynamicVertexAllocator(GrMeshDrawOp::Target * target,sk_sp<const GrBuffer> * vertexBuffer,int * baseVertex)39     GrEagerDynamicVertexAllocator(GrMeshDrawOp::Target* target,
40                                   sk_sp<const GrBuffer>* vertexBuffer,
41                                   int* baseVertex)
42             : fTarget(target)
43             , fVertexBuffer(vertexBuffer)
44             , fBaseVertex(baseVertex) {
45     }
46 
47 #ifdef SK_DEBUG
~GrEagerDynamicVertexAllocator()48     ~GrEagerDynamicVertexAllocator() override {
49         SkASSERT(!fLockCount);
50     }
51 #endif
52 
53     // Un-shadow GrEagerVertexAllocator::lock<T>.
54     using GrEagerVertexAllocator::lock;
55 
56     // Mark "final" as a hint for the compiler to not use the vtable.
lock(size_t stride,int eagerCount)57     void* lock(size_t stride, int eagerCount) final {
58         SkASSERT(!fLockCount);
59         SkASSERT(eagerCount);
60         if (void* data = fTarget->makeVertexSpace(stride, eagerCount, fVertexBuffer, fBaseVertex)) {
61             fLockStride = stride;
62             fLockCount = eagerCount;
63             return data;
64         }
65         fVertexBuffer->reset();
66         *fBaseVertex = 0;
67         return nullptr;
68     }
69 
70     // Mark "final" as a hint for the compiler to not use the vtable.
unlock(int actualCount)71     void unlock(int actualCount) final {
72         SkASSERT(fLockCount);
73         SkASSERT(actualCount <= fLockCount);
74         fTarget->putBackVertices(fLockCount - actualCount, fLockStride);
75         if (!actualCount) {
76             fVertexBuffer->reset();
77             *fBaseVertex = 0;
78         }
79         fLockCount = 0;
80     }
81 
82 private:
83     GrMeshDrawOp::Target* const fTarget;
84     sk_sp<const GrBuffer>* const fVertexBuffer;
85     int* const fBaseVertex;
86 
87     size_t fLockStride;
88     int fLockCount = 0;
89 };
90 
91 class GrCpuVertexAllocator : public GrEagerVertexAllocator {
92 public:
93     GrCpuVertexAllocator() = default;
94 
95 #ifdef SK_DEBUG
~GrCpuVertexAllocator()96     ~GrCpuVertexAllocator() override {
97         SkASSERT(!fLockStride && !fVertices && !fVertexData);
98     }
99 #endif
100 
101     void* lock(size_t stride, int eagerCount) override;
102     void unlock(int actualCount) override;
103 
104     sk_sp<GrThreadSafeCache::VertexData> detachVertexData();
105 
106 private:
107     sk_sp<GrThreadSafeCache::VertexData> fVertexData;
108 
109     void*  fVertices = nullptr;
110     size_t fLockStride = 0;
111 };
112 
113 #endif
114