Flutter Engine
The Flutter Engine
PaintParamsKey.cpp
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
9
16
17using namespace skia_private;
18
19namespace skgpu::graphite {
20
21//--------------------------------------------------------------------------------------------------
22// PaintParamsKeyBuilder
23
24#ifdef SK_DEBUG
25
26void PaintParamsKeyBuilder::checkReset() {
27 SkASSERT(!fLocked);
28 SkASSERT(fData.empty());
29 SkASSERT(fStack.empty());
30}
31
32void PaintParamsKeyBuilder::pushStack(int32_t codeSnippetID) {
33 SkASSERT(fDict->isValidID(codeSnippetID));
34
35 if (!fStack.empty()) {
36 fStack.back().fNumActualChildren++;
37 SkASSERT(fStack.back().fNumActualChildren <= fStack.back().fNumExpectedChildren);
38 }
39
40 const ShaderSnippet* snippet = fDict->getEntry(codeSnippetID);
41 fStack.push_back({codeSnippetID, snippet->fNumChildren});
42}
43
44void PaintParamsKeyBuilder::popStack() {
45 SkASSERT(!fStack.empty());
46 SkASSERT(fStack.back().fNumActualChildren == fStack.back().fNumExpectedChildren);
47 fStack.pop_back();
48}
49
50#endif // SK_DEBUG
51
52//--------------------------------------------------------------------------------------------------
53// PaintParamsKey
54
56 uint32_t* newData = arena->makeArrayDefault<uint32_t>(fData.size());
57 memcpy(newData, fData.data(), fData.size_bytes());
58 return PaintParamsKey({newData, fData.size()});
59}
60
61
62const ShaderNode* PaintParamsKey::createNode(const ShaderCodeDictionary* dict,
63 int* currentIndex,
64 SkArenaAlloc* arena) const {
65 SkASSERT(*currentIndex < SkTo<int>(fData.size()));
66 const int32_t index = (*currentIndex)++;
67 const int32_t id = fData[index];
68
69 const ShaderSnippet* entry = dict->getEntry(id);
70 if (!entry) {
71 SKGPU_LOG_E("Unknown snippet ID in key: %d", id);
72 return nullptr;
73 }
74
75 SkSpan<const uint32_t> dataSpan = {};
76 if (entry->storesData()) {
77 // Gather any additional data that should be passed into ShaderNode creation. If the next
78 // entry is 0, that simply indicates there is no embedded data to store. Iterate
79 // currentIndex past the stored data length entry.
80 const int storedDataLengthIdx = (*currentIndex)++;
81 SkASSERT(storedDataLengthIdx < SkTo<int>(fData.size()));
82 const int dataLength = fData[storedDataLengthIdx];
83 SkASSERT(storedDataLengthIdx + dataLength < SkTo<int>(fData.size()));
84
85 if (dataLength) {
86 dataSpan = fData.subspan(storedDataLengthIdx + 1, dataLength);
87 // Iterate past the length of data
88 *currentIndex += dataLength;
89 }
90 }
91
92 const ShaderNode** childArray = arena->makeArray<const ShaderNode*>(entry->fNumChildren);
93 for (int i = 0; i < entry->fNumChildren; ++i) {
94 const ShaderNode* child = this->createNode(dict, currentIndex, arena);
95 if (!child) {
96 return nullptr;
97 }
98 childArray[i] = child;
99 }
100
101 return arena->make<ShaderNode>(entry,
102 SkSpan(childArray, entry->fNumChildren),
103 id,
104 index,
105 dataSpan);
106}
107
109 SkArenaAlloc* arena) const {
110 // TODO: Once the PaintParamsKey creation is organized to represent a single tree starting at
111 // the final blend, there will only be a single root node and this can be simplified.
112 // For now, we don't know how many roots there are, so collect them into a local array before
113 // copying into the arena.
114 const int keySize = SkTo<int>(fData.size());
115
116 // Normal PaintParams creation will have up to 7 roots for the different stages.
118 int currentIndex = 0;
119 while (currentIndex < keySize) {
120 const ShaderNode* root = this->createNode(dict, &currentIndex, arena);
121 if (!root) {
122 return {}; // a bad key
123 }
124 roots.push_back(root);
125 }
126
127 // Copy the accumulated roots into a span stored in the arena
128 const ShaderNode** rootSpan = arena->makeArray<const ShaderNode*>(roots.size());
129 memcpy(rootSpan, roots.data(), roots.size_bytes());
130 return SkSpan(rootSpan, roots.size());
131}
132
133static int key_to_string(SkString* str,
134 const ShaderCodeDictionary* dict,
136 int currentIndex,
137 bool includeData) {
138 SkASSERT(currentIndex < SkTo<int>(keyData.size()));
139
140 uint32_t id = keyData[currentIndex++];
141 auto entry = dict->getEntry(id);
142 if (!entry) {
143 str->append("UnknownCodeSnippetID:");
144 str->appendS32(id);
145 str->append(" ");
146 return currentIndex;
147 }
148
149 std::string_view name = entry->fName;
150 if (skstd::ends_with(name, "Shader")) {
151 name.remove_suffix(6);
152 }
153 str->append(name);
154
155 if (entry->storesData()) {
156 SkASSERT(currentIndex + 1 < SkTo<int>(keyData.size()));
157 const int dataLength = keyData[currentIndex++];
158 SkASSERT(currentIndex + dataLength < SkTo<int>(keyData.size()));
159
160 str->append(" fData(size: ");
161 str->appendU32(dataLength);
162 str->append(")");
163
164 if (includeData) {
165 str->append(":[");
166 for (int i = 0; i < dataLength; i++) {
167 str->append(" ");
168 str->appendU32(keyData[currentIndex + i]);
169 }
170 str->append(" ]");
171 }
172
173 currentIndex += dataLength;
174 }
175
176 if (entry->fNumChildren > 0) {
177 str->append(" [ ");
178 for (int i = 0; i < entry->fNumChildren; ++i) {
179 currentIndex = key_to_string(str, dict, keyData, currentIndex, includeData);
180 }
181 str->append("]");
182 }
183
184 str->append(" ");
185 return currentIndex;
186}
187
188SkString PaintParamsKey::toString(const ShaderCodeDictionary* dict, bool includeData) const {
189 SkString str;
190 const int keySize = SkTo<int>(fData.size());
191 for (int currentIndex = 0; currentIndex < keySize;) {
192 currentIndex = key_to_string(&str, dict, fData, currentIndex, includeData);
193 }
194 return str.isEmpty() ? SkString("(empty)") : str;
195}
196
197#ifdef SK_DEBUG
198
199static int dump_node(const ShaderCodeDictionary* dict,
201 int currentIndex,
202 int indent) {
203 SkASSERT(currentIndex < SkTo<int>(keyData.size()));
204
205 SkDebugf("%*c", 2 * indent, ' ');
206
207 int32_t id = keyData[currentIndex++];
208 auto entry = dict->getEntry(id);
209 if (!entry) {
210 SkDebugf("[%d] unknown block!\n", id);
211 return currentIndex;
212 }
213
214 SkDebugf("[%d] %s\n", id, entry->fStaticFunctionName);
215 for (int i = 0; i < entry->fNumChildren; ++i) {
216 currentIndex = dump_node(dict, keyData, currentIndex, indent + 1);
217 }
218
219 if (entry->storesData()) {
220 SkASSERT(currentIndex < SkTo<int>(keyData.size()));
221 const int dataLength = keyData[currentIndex++];
222 SkASSERT(currentIndex + dataLength < SkTo<int>(keyData.size()));
223 SkDebugf("%*c", (2 * indent + 1), ' ');
224 SkDebugf("Snippet data (size: %i): ", dataLength);
225
226 if (dataLength == 0) {
227 SkDebugf("0 (no data)\n");
228 } else {
229 for (int i = currentIndex; i < dataLength; i++) {
230 SkDebugf( "%d ", keyData[currentIndex + i]);
231 }
232 SkDebugf("\n");
233 currentIndex += dataLength;
234 }
235 }
236 return currentIndex;
237}
238
239void PaintParamsKey::dump(const ShaderCodeDictionary* dict, UniquePaintParamsID id) const {
240 const int keySize = SkTo<int>(fData.size());
241
242 SkDebugf("--------------------------------------\n");
243 SkDebugf("%u PaintParamsKey (keySize: %d):\n", id.asUInt(), keySize);
244
245 int currentIndex = 0;
246 while (currentIndex < keySize) {
247 currentIndex = dump_node(dict, fData, currentIndex, 1);
248 }
249}
250
251#endif // SK_DEBUG
252
253} // namespace skgpu::graphite
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
Definition: SkYUVMath.cpp:629
T * makeArrayDefault(size_t count)
Definition: SkArenaAlloc.h:171
T * makeArray(size_t count)
Definition: SkArenaAlloc.h:181
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
constexpr SkSpan< T > subspan(size_t offset) const
Definition: SkSpan_impl.h:105
constexpr T * data() const
Definition: SkSpan_impl.h:94
constexpr size_t size_bytes() const
Definition: SkSpan_impl.h:97
constexpr size_t size() const
Definition: SkSpan_impl.h:95
bool isEmpty() const
Definition: SkString.h:130
void append(const char text[])
Definition: SkString.h:203
void appendS32(int32_t value)
Definition: SkString.h:208
void appendU32(uint32_t value)
Definition: SkString.h:210
constexpr PaintParamsKey(const PaintParamsKey &)=default
PaintParamsKey clone(SkArenaAlloc *) const
SkString toString(const ShaderCodeDictionary *dict, bool includeData) const
SkSpan< const ShaderNode * > getRootNodes(const ShaderCodeDictionary *, SkArenaAlloc *) const
const ShaderSnippet * getEntry(int codeSnippetID) const SK_EXCLUDES(fSpinLock)
bool empty() const
Definition: SkTArray.h:199
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
string root
Definition: scale_cpu.py:20
static int key_to_string(SkString *str, const ShaderCodeDictionary *dict, SkSpan< const uint32_t > keyData, int currentIndex, bool includeData)
constexpr bool ends_with(std::string_view str, std::string_view suffix)
Definition: SkStringView.h:28
const uintptr_t id