1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Feature.h: Definition of structs to hold feature/workaround information.
7 //
8 
9 #ifndef ANGLE_PLATFORM_FEATURE_H_
10 #define ANGLE_PLATFORM_FEATURE_H_
11 
12 #include <map>
13 #include <string>
14 #include <vector>
15 
16 #define ANGLE_FEATURE_CONDITION(set, feature, cond)       \
17     do                                                    \
18     {                                                     \
19         (set)->feature.enabled   = cond;                  \
20         (set)->feature.condition = ANGLE_STRINGIFY(cond); \
21     } while (0)
22 
23 namespace angle
24 {
25 
26 enum class FeatureCategory
27 {
28     FrontendWorkarounds,
29     FrontendFeatures,
30     OpenGLWorkarounds,
31     D3DWorkarounds,
32     D3DCompilerWorkarounds,
33     VulkanWorkarounds,
34     VulkanFeatures,
35     MetalFeatures,
36 };
37 
38 constexpr char kFeatureCategoryFrontendWorkarounds[]    = "Frontend workarounds";
39 constexpr char kFeatureCategoryFrontendFeatures[]       = "Frontend features";
40 constexpr char kFeatureCategoryOpenGLWorkarounds[]      = "OpenGL workarounds";
41 constexpr char kFeatureCategoryD3DWorkarounds[]         = "D3D workarounds";
42 constexpr char kFeatureCategoryD3DCompilerWorkarounds[] = "D3D compiler workarounds";
43 constexpr char kFeatureCategoryVulkanWorkarounds[]      = "Vulkan workarounds";
44 constexpr char kFeatureCategoryVulkanFeatures[]         = "Vulkan features";
45 constexpr char kFeatureCategoryMetalFeatures[]          = "Metal features";
46 constexpr char kFeatureCategoryUnknown[]                = "Unknown";
47 
FeatureCategoryToString(const FeatureCategory & fc)48 inline const char *FeatureCategoryToString(const FeatureCategory &fc)
49 {
50     switch (fc)
51     {
52         case FeatureCategory::FrontendWorkarounds:
53             return kFeatureCategoryFrontendWorkarounds;
54             break;
55 
56         case FeatureCategory::FrontendFeatures:
57             return kFeatureCategoryFrontendFeatures;
58             break;
59 
60         case FeatureCategory::OpenGLWorkarounds:
61             return kFeatureCategoryOpenGLWorkarounds;
62             break;
63 
64         case FeatureCategory::D3DWorkarounds:
65             return kFeatureCategoryD3DWorkarounds;
66             break;
67 
68         case FeatureCategory::D3DCompilerWorkarounds:
69             return kFeatureCategoryD3DCompilerWorkarounds;
70             break;
71 
72         case FeatureCategory::VulkanWorkarounds:
73             return kFeatureCategoryVulkanWorkarounds;
74             break;
75 
76         case FeatureCategory::VulkanFeatures:
77             return kFeatureCategoryVulkanFeatures;
78             break;
79 
80         case FeatureCategory::MetalFeatures:
81             return kFeatureCategoryMetalFeatures;
82             break;
83 
84         default:
85             return kFeatureCategoryUnknown;
86             break;
87     }
88 }
89 
90 constexpr char kFeatureStatusEnabled[]  = "enabled";
91 constexpr char kFeatureStatusDisabled[] = "disabled";
92 
FeatureStatusToString(const bool & status)93 inline const char *FeatureStatusToString(const bool &status)
94 {
95     if (status)
96     {
97         return kFeatureStatusEnabled;
98     }
99     return kFeatureStatusDisabled;
100 }
101 
102 struct Feature;
103 
104 using FeatureMap  = std::map<std::string, Feature *>;
105 using FeatureList = std::vector<const Feature *>;
106 
107 struct Feature
108 {
109     Feature(const Feature &other);
110     Feature(const char *name,
111             const FeatureCategory &category,
112             const char *description,
113             FeatureMap *const mapPtr,
114             const char *bug);
115     ~Feature();
116 
117     // The name of the workaround, lowercase, camel_case
118     const char *const name;
119 
120     // The category that the workaround belongs to. Eg. "Vulkan workarounds"
121     const FeatureCategory category;
122 
123     // A short description to be read by the user.
124     const char *const description;
125 
126     // A link to the bug, if any
127     const char *const bug;
128 
129     // Whether the workaround is enabled or not. Determined by heuristics like vendor ID and
130     // version, but may be overriden to any value.
131     bool enabled = false;
132 
133     // A stingified version of the condition used to set 'enabled'. ie "IsNvidia() && IsApple()"
134     const char *condition;
135 };
136 
137 inline Feature::Feature(const Feature &other) = default;
138 inline Feature::Feature(const char *name,
139                         const FeatureCategory &category,
140                         const char *description,
141                         FeatureMap *const mapPtr,
142                         const char *bug = "")
name(name)143     : name(name),
144       category(category),
145       description(description),
146       bug(bug),
147       enabled(false),
148       condition("")
149 {
150     if (mapPtr != nullptr)
151     {
152         (*mapPtr)[std::string(name)] = this;
153     }
154 }
155 
156 inline Feature::~Feature() = default;
157 
158 struct FeatureSetBase
159 {
160   public:
161     FeatureSetBase();
162     ~FeatureSetBase();
163 
164   private:
165     // Non-copyable
166     FeatureSetBase(const FeatureSetBase &other) = delete;
167     FeatureSetBase &operator=(const FeatureSetBase &other) = delete;
168 
169   protected:
170     FeatureMap members = FeatureMap();
171 
172   public:
overrideFeaturesFeatureSetBase173     void overrideFeatures(const std::vector<std::string> &featureNames, bool enabled)
174     {
175         for (const std::string &name : featureNames)
176         {
177             if (members.find(name) != members.end())
178             {
179                 members[name]->enabled = enabled;
180             }
181         }
182     }
183 
populateFeatureListFeatureSetBase184     void populateFeatureList(FeatureList *features) const
185     {
186         for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++)
187         {
188             features->push_back(it->second);
189         }
190     }
191 
getFeaturesFeatureSetBase192     const FeatureMap &getFeatures() const { return members; }
193 };
194 
195 inline FeatureSetBase::FeatureSetBase()  = default;
196 inline FeatureSetBase::~FeatureSetBase() = default;
197 
198 }  // namespace angle
199 
200 #endif  // ANGLE_PLATFORM_WORKAROUND_H_
201