blob: 73531f48c0c3d0212ad295b4f1ed547907fcd710 [file] [log] [blame]
Chris Daltond081dce2020-01-23 12:09:04 -07001/*
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
Robert Phillips98b066c2021-04-22 10:51:58 -040011#include "src/gpu/GrThreadSafeCache.h"
Chris Daltond081dce2020-01-23 12:09:04 -070012#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.
23class GrEagerVertexAllocator {
24public:
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
32 virtual ~GrEagerVertexAllocator() {}
33};
34
35// GrEagerVertexAllocator implementation that uses GrMeshDrawOp::Target::makeVertexSpace and
36// GrMeshDrawOp::Target::putBackVertices.
37class GrEagerDynamicVertexAllocator : public GrEagerVertexAllocator {
38public:
39 GrEagerDynamicVertexAllocator(GrMeshDrawOp::Target* target,
Robert Phillips3ac83b2f2020-10-26 13:50:57 -040040 sk_sp<const GrBuffer>* vertexBuffer,
41 int* baseVertex)
Chris Daltond081dce2020-01-23 12:09:04 -070042 : fTarget(target)
43 , fVertexBuffer(vertexBuffer)
44 , fBaseVertex(baseVertex) {
45 }
46
47#ifdef SK_DEBUG
48 ~GrEagerDynamicVertexAllocator() override {
49 SkASSERT(!fLockCount);
50 }
51#endif
52
Chris Dalton42915c22020-04-22 16:24:43 -060053 // Un-shadow GrEagerVertexAllocator::lock<T>.
54 using GrEagerVertexAllocator::lock;
55
56 // Mark "final" as a hint for the compiler to not use the vtable.
57 void* lock(size_t stride, int eagerCount) final {
Chris Daltond081dce2020-01-23 12:09:04 -070058 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
Chris Dalton42915c22020-04-22 16:24:43 -060070 // Mark "final" as a hint for the compiler to not use the vtable.
71 void unlock(int actualCount) final {
Chris Daltond081dce2020-01-23 12:09:04 -070072 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
82private:
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
Robert Phillips98b066c2021-04-22 10:51:58 -040091class GrCpuVertexAllocator : public GrEagerVertexAllocator {
92public:
93 GrCpuVertexAllocator() = default;
94
95#ifdef SK_DEBUG
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
106private:
107 sk_sp<GrThreadSafeCache::VertexData> fVertexData;
108
109 void* fVertices = nullptr;
110 size_t fLockStride = 0;
111};
112
Chris Daltond081dce2020-01-23 12:09:04 -0700113#endif