Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
PaintParamsKey.h
Go to the documentation of this file.
1/*
2 * Copyright 2022 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 skgpu_graphite_PaintParamsKey_DEFINED
9#define skgpu_graphite_PaintParamsKey_DEFINED
10
11#include "include/core/SkSpan.h"
15#include "src/core/SkChecksum.h"
17
18#include <limits>
19#include <cstring> // for memcmp
20
21class SkArenaAlloc;
22
23namespace skgpu::graphite {
24
25class ShaderCodeDictionary;
26class ShaderNode;
27
28// This class is a compact representation of the shader needed to implement a given
29// PaintParams. Its structure is a series of nodes where each node consists of:
30// 4 bytes: code-snippet ID
31// N child nodes, where N is the constant number of children defined by the ShaderCodeDictionary
32// for the node's snippet ID.
33//
34// All children of a child node are stored in the key before the next child is encoded in the key,
35// e.g. iterating the data in a key is a depth-first traversal of the node tree.
37public:
38 // PaintParamsKey can only be created by using a PaintParamsKeyBuilder or by cloning the key
39 // data from a Builder-owned key, but they can be passed around by value after that.
40 constexpr PaintParamsKey(const PaintParamsKey&) = default;
41
42 ~PaintParamsKey() = default;
44
46 bool isValid() const { return !fData.empty(); }
47
48 // Return a PaintParamsKey whose data is owned by the provided arena and is not attached to
49 // a PaintParamsKeyBuilder. The caller must ensure that the SkArenaAlloc remains alive longer
50 // than the returned key.
52
53 // Converts the key into a forest of ShaderNode trees. If the key is valid this will return at
54 // least one root node. If the key contains unknown shader snippet IDs, returns an empty span.
55 // All shader nodes, and the returned span's backing data, are owned by the provided arena.
56 // TODO: Strengthen PaintParams key generation so we can assume there's only ever one root node
57 // representing the final blend (either a shader blend (with 2 children: main effect & dst) or
58 // a fixed function blend (with 1 child being the main effect)).
60
61 // Converts the key to a structured list of snippet names for debugging or labeling purposes.
62 SkString toString(const ShaderCodeDictionary* dict) const;
63
64#ifdef SK_DEBUG
65 void dump(const ShaderCodeDictionary*) const;
66#endif
67
68 bool operator==(const PaintParamsKey& that) const {
69 return fData.size() == that.fData.size() &&
70 !memcmp(fData.data(), that.fData.data(), fData.size());
71 }
72 bool operator!=(const PaintParamsKey& that) const { return !(*this == that); }
73
74 struct Hash {
75 uint32_t operator()(const PaintParamsKey& k) const {
76 return SkChecksum::Hash32(k.fData.data(), k.fData.size_bytes());
77 }
78 };
79
80private:
81 friend class PaintParamsKeyBuilder; // for the parented-data ctor
82
83 constexpr PaintParamsKey(SkSpan<const int32_t> span) : fData(span) {}
84
85 // Returns null if the node or any of its children have an invalid snippet ID. Recursively
86 // creates a node and all of its children, incrementing 'currentIndex' by the total number of
87 // nodes created.
88 const ShaderNode* createNode(const ShaderCodeDictionary*,
89 int* currentIndex,
90 SkArenaAlloc* arena) const;
91
92 // The memory referenced in 'fData' is always owned by someone else. It either shares the span
93 // of from the Builder, or clone() puts the span in an arena.
95};
96
97// The PaintParamsKeyBuilder and the PaintParamsKeys snapped from it share the same
98// underlying block of memory. When an PaintParamsKey is snapped from the builder it 'locks'
99// the memory and 'unlocks' it in its destructor. Because of this relationship, the builder
100// can only have one extant key and that key must be destroyed before the builder can be reused
101// to create another one.
102//
103// This arrangement is intended to improve performance in the expected case, where a builder is
104// being used in a tight loop to generate keys which can be recycled once they've been used to
105// find the dictionary's matching uniqueID. We don't expect the cost of copying the key's memory
106// into the dictionary to be prohibitive since that should be infrequent.
108public:
110 SkDEBUGCODE(fDict = dict;)
111 }
112
114
115 void beginBlock(BuiltInCodeSnippetID id) { this->beginBlock(static_cast<int32_t>(id)); }
116 void beginBlock(int32_t codeSnippetID) {
117 SkASSERT(!fLocked);
118 SkDEBUGCODE(this->pushStack(codeSnippetID);)
119 fData.push_back(codeSnippetID);
120 }
121
122 // TODO: Have endBlock() be handled automatically with RAII, in which case we could have it
123 // validate the snippet ID being popped off the stack frame.
124 void endBlock() {
125 SkDEBUGCODE(this->popStack();)
126 }
127
128#ifdef SK_DEBUG
129 // Check that the builder has been reset to its initial state prior to creating a new key.
130 void checkReset();
131#endif
132
133 // Helper to add blocks that don't have children
135 this->beginBlock(id);
136 this->endBlock();
137 }
138
139private:
140 friend class AutoLockBuilderAsKey; // for lockAsKey() and unlock()
141
142 // Returns a view of this builder as a PaintParamsKey. The Builder cannot be used until the
143 // returned Key goes out of scope.
144 PaintParamsKey lockAsKey() {
145 SkASSERT(!fLocked); // lockAsKey() is not re-entrant
146 SkASSERT(fStack.empty()); // All beginBlocks() had a matching endBlock()
147
148 SkDEBUGCODE(fLocked = true;)
149 return PaintParamsKey({fData.data(), fData.size()});
150 }
151
152 // Invalidates any PaintParamsKey returned by lockAsKey() unless it has been cloned.
153 void unlock() {
154 SkASSERT(fLocked);
155 fData.clear();
156
157 SkDEBUGCODE(fLocked = false;)
158 SkDEBUGCODE(fStack.clear();)
159 SkDEBUGCODE(this->checkReset();)
160 }
161
162 // The data array uses clear() on unlock so that it's underlying storage and repeated use of the
163 // builder will hit a high-water mark and avoid lots of allocations when recording draws.
165
166#ifdef SK_DEBUG
167 void pushStack(int32_t codeSnippetID);
168 void popStack();
169
170 // Information about the current block being written
171 struct StackFrame {
172 int fCodeSnippetID;
173 int fNumExpectedChildren;
174 int fNumActualChildren = 0;
175 };
176
177 const ShaderCodeDictionary* fDict;
179 bool fLocked = false;
180#endif
181};
182
184public:
186 : fBuilder(builder)
187 , fKey(builder->lockAsKey()) {}
188
190 fBuilder->unlock();
191 }
192
193 // Use as a PaintParamsKey
194 const PaintParamsKey& operator*() const { return fKey; }
195 const PaintParamsKey* operator->() const { return &fKey; }
196
197private:
198 PaintParamsKeyBuilder* fBuilder;
199 PaintParamsKey fKey;
200};
201
202} // namespace skgpu::graphite
203
204#endif // skgpu_graphite_PaintParamsKey_DEFINED
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
constexpr T * data() const
Definition SkSpan_impl.h:94
constexpr bool empty() const
Definition SkSpan_impl.h:96
constexpr size_t size_bytes() const
Definition SkSpan_impl.h:97
constexpr size_t size() const
Definition SkSpan_impl.h:95
const PaintParamsKey & operator*() const
AutoLockBuilderAsKey(PaintParamsKeyBuilder *builder)
const PaintParamsKey * operator->() const
void addBlock(BuiltInCodeSnippetID id)
void beginBlock(int32_t codeSnippetID)
PaintParamsKeyBuilder(const ShaderCodeDictionary *dict)
void beginBlock(BuiltInCodeSnippetID id)
SkString toString(const ShaderCodeDictionary *dict) const
constexpr PaintParamsKey(const PaintParamsKey &)=default
bool operator==(const PaintParamsKey &that) const
PaintParamsKey clone(SkArenaAlloc *) const
PaintParamsKey & operator=(const PaintParamsKey &)=default
static constexpr PaintParamsKey Invalid()
SkSpan< const ShaderNode * > getRootNodes(const ShaderCodeDictionary *, SkArenaAlloc *) const
bool operator!=(const PaintParamsKey &that) const
int size() const
Definition SkTArray.h:416
uint32_t Hash32(const void *data, size_t bytes, uint32_t seed)
uint32_t operator()(const PaintParamsKey &k) const