• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SkShaderCodeDictionary_DEFINED
9 #define SkShaderCodeDictionary_DEFINED
10 
11 #include <array>
12 #include <unordered_map>
13 #include <vector>
14 #include "include/core/SkSpan.h"
15 #include "include/private/SkSpinlock.h"
16 #include "include/private/SkUniquePaintParamsID.h"
17 #include "src/core/SkArenaAlloc.h"
18 #include "src/core/SkPaintParamsKey.h"
19 #include "src/core/SkUniform.h"
20 
21 class SkShaderInfo {
22 public:
23     struct SnippetEntry;
24     using GenerateGlueCodeForEntry = std::string (*)(const std::string& resultName,
25                                                      int entryIndex, // for uniform name mangling
26                                                      const SnippetEntry&,
27                                                      const std::vector<std::string>& childNames,
28                                                      int indent);
29 
30     struct SnippetEntry {
31         SkSpan<const SkUniform> fUniforms;
32         const char* fStaticFunctionName;
33         const char* fStaticSkSL;
34         GenerateGlueCodeForEntry fGlueCodeGenerator;
35         int fNumChildren;
36     };
37 
add(const SnippetEntry & entry)38     void add(const SnippetEntry& entry) {
39         fEntries.push_back(entry);
40     }
41 
42     // TODO: writing to color should be a property of the SnippetEntries and accumulated as the
43     // entries are added. _Not_ set manually via 'setWritesColor'.
setWritesColor()44     void setWritesColor() { fWritesColor = true; }
writesColor()45     bool writesColor() const { return fWritesColor; }
46 
47 #if SK_SUPPORT_GPU && defined(SK_GRAPHITE_ENABLED) && defined(SK_METAL)
48     std::string toSkSL() const;
49 #endif
50 
51 private:
52     std::string emitGlueCodeForEntry(int* entryIndex, std::string* result, int indent) const;
53 
54     std::vector<SnippetEntry> fEntries;
55     bool fWritesColor = false;
56 };
57 
58 class SkShaderCodeDictionary {
59 public:
60     SkShaderCodeDictionary();
61 
62     struct Entry {
63     public:
uniqueIDEntry64         SkUniquePaintParamsID uniqueID() const {
65             SkASSERT(fUniqueID.isValid());
66             return fUniqueID;
67         }
paintParamsKeyEntry68         const SkPaintParamsKey* paintParamsKey() const { return fKey.get(); }
69 
70     private:
71         friend class SkShaderCodeDictionary;
72 
EntryEntry73         Entry(std::unique_ptr<SkPaintParamsKey> key) : fKey(std::move(key)) {}
74 
setUniqueIDEntry75         void setUniqueID(uint32_t newID) {
76             SkASSERT(!fUniqueID.isValid());
77             fUniqueID = SkUniquePaintParamsID(newID);
78         }
79 
80         SkUniquePaintParamsID fUniqueID;  // fixed-size (uint32_t) unique ID assigned to a key
81         std::unique_ptr<SkPaintParamsKey> fKey; // variable-length paint key descriptor
82     };
83 
84     const Entry* findOrCreate(std::unique_ptr<SkPaintParamsKey>) SK_EXCLUDES(fSpinLock);
85 
86     const Entry* lookup(SkUniquePaintParamsID) const SK_EXCLUDES(fSpinLock);
87 
88     SkSpan<const SkUniform> getUniforms(SkBuiltInCodeSnippetID) const;
89     const SkShaderInfo::SnippetEntry* getEntry(SkBuiltInCodeSnippetID) const;
90 
91     void getShaderInfo(SkUniquePaintParamsID, SkShaderInfo*);
92 
maxCodeSnippetID()93     int maxCodeSnippetID() const {
94         return static_cast<int>(SkBuiltInCodeSnippetID::kLast) + fUserDefinedCodeSnippets.size();
95     }
96 
97     // TODO: this is still experimental but, most likely, it will need to be made thread-safe
98     // It returns the code snippet ID to use to identify the supplied user-defined code
99     // TODO: add hooks for user to actually provide code.
100     int addUserDefinedSnippet();
101 
102 private:
103     Entry* makeEntry(std::unique_ptr<SkPaintParamsKey>);
104 
105     struct Hash {
106         size_t operator()(const SkPaintParamsKey*) const;
107     };
108 
109     std::array<SkShaderInfo::SnippetEntry, kBuiltInCodeSnippetIDCount> fBuiltInCodeSnippets;
110     std::vector<SkShaderInfo::SnippetEntry> fUserDefinedCodeSnippets;
111 
112     // TODO: can we do something better given this should have write-seldom/read-often behavior?
113     mutable SkSpinlock fSpinLock;
114 
115     std::unordered_map<const SkPaintParamsKey*, Entry*, Hash> fHash SK_GUARDED_BY(fSpinLock);
116     std::vector<Entry*> fEntryVector SK_GUARDED_BY(fSpinLock);
117 
118     SkArenaAlloc fArena{256};
119 };
120 
121 #endif // SkShaderCodeDictionary_DEFINED
122