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 MetalWorkarounds,
37 };
38
39 constexpr char kFeatureCategoryFrontendWorkarounds[] = "Frontend workarounds";
40 constexpr char kFeatureCategoryFrontendFeatures[] = "Frontend features";
41 constexpr char kFeatureCategoryOpenGLWorkarounds[] = "OpenGL workarounds";
42 constexpr char kFeatureCategoryD3DWorkarounds[] = "D3D workarounds";
43 constexpr char kFeatureCategoryD3DCompilerWorkarounds[] = "D3D compiler workarounds";
44 constexpr char kFeatureCategoryVulkanWorkarounds[] = "Vulkan workarounds";
45 constexpr char kFeatureCategoryVulkanFeatures[] = "Vulkan features";
46 constexpr char kFeatureCategoryMetalFeatures[] = "Metal features";
47 constexpr char kFeatureCategoryMetalWorkarounds[] = "Metal workarounds";
48 constexpr char kFeatureCategoryUnknown[] = "Unknown";
49
FeatureCategoryToString(const FeatureCategory & fc)50 inline const char *FeatureCategoryToString(const FeatureCategory &fc)
51 {
52 switch (fc)
53 {
54 case FeatureCategory::FrontendWorkarounds:
55 return kFeatureCategoryFrontendWorkarounds;
56 break;
57
58 case FeatureCategory::FrontendFeatures:
59 return kFeatureCategoryFrontendFeatures;
60 break;
61
62 case FeatureCategory::OpenGLWorkarounds:
63 return kFeatureCategoryOpenGLWorkarounds;
64 break;
65
66 case FeatureCategory::D3DWorkarounds:
67 return kFeatureCategoryD3DWorkarounds;
68 break;
69
70 case FeatureCategory::D3DCompilerWorkarounds:
71 return kFeatureCategoryD3DCompilerWorkarounds;
72 break;
73
74 case FeatureCategory::VulkanWorkarounds:
75 return kFeatureCategoryVulkanWorkarounds;
76 break;
77
78 case FeatureCategory::VulkanFeatures:
79 return kFeatureCategoryVulkanFeatures;
80 break;
81
82 case FeatureCategory::MetalFeatures:
83 return kFeatureCategoryMetalFeatures;
84 break;
85
86 case FeatureCategory::MetalWorkarounds:
87 return kFeatureCategoryMetalWorkarounds;
88 break;
89
90 default:
91 return kFeatureCategoryUnknown;
92 break;
93 }
94 }
95
96 constexpr char kFeatureStatusEnabled[] = "enabled";
97 constexpr char kFeatureStatusDisabled[] = "disabled";
98
FeatureStatusToString(const bool & status)99 inline const char *FeatureStatusToString(const bool &status)
100 {
101 if (status)
102 {
103 return kFeatureStatusEnabled;
104 }
105 return kFeatureStatusDisabled;
106 }
107
108 struct Feature;
109
110 using FeatureMap = std::map<std::string, Feature *>;
111 using FeatureList = std::vector<const Feature *>;
112
113 struct Feature
114 {
115 Feature(const Feature &other);
116 Feature(const char *name,
117 const FeatureCategory &category,
118 const char *description,
119 FeatureMap *const mapPtr,
120 const char *bug);
121 ~Feature();
122
123 // The name of the workaround, lowercase, camel_case
124 const char *const name;
125
126 // The category that the workaround belongs to. Eg. "Vulkan workarounds"
127 const FeatureCategory category;
128
129 // A short description to be read by the user.
130 const char *const description;
131
132 // A link to the bug, if any
133 const char *const bug;
134
135 // Whether the workaround is enabled or not. Determined by heuristics like vendor ID and
136 // version, but may be overriden to any value.
137 bool enabled = false;
138
139 // A stingified version of the condition used to set 'enabled'. ie "IsNvidia() && IsApple()"
140 const char *condition;
141 };
142
143 inline Feature::Feature(const Feature &other) = default;
144 inline Feature::Feature(const char *name,
145 const FeatureCategory &category,
146 const char *description,
147 FeatureMap *const mapPtr,
148 const char *bug = "")
name(name)149 : name(name),
150 category(category),
151 description(description),
152 bug(bug),
153 enabled(false),
154 condition("")
155 {
156 if (mapPtr != nullptr)
157 {
158 (*mapPtr)[std::string(name)] = this;
159 }
160 }
161
162 inline Feature::~Feature() = default;
163
164 struct FeatureSetBase
165 {
166 public:
167 FeatureSetBase();
168 ~FeatureSetBase();
169
170 private:
171 // Non-copyable
172 FeatureSetBase(const FeatureSetBase &other) = delete;
173 FeatureSetBase &operator=(const FeatureSetBase &other) = delete;
174
175 protected:
176 FeatureMap members = FeatureMap();
177
178 public:
overrideFeaturesFeatureSetBase179 void overrideFeatures(const std::vector<std::string> &featureNames, bool enabled)
180 {
181 for (const std::string &name : featureNames)
182 {
183 if (members.find(name) != members.end())
184 {
185 members[name]->enabled = enabled;
186 }
187 }
188 }
189
populateFeatureListFeatureSetBase190 void populateFeatureList(FeatureList *features) const
191 {
192 for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++)
193 {
194 features->push_back(it->second);
195 }
196 }
197
getFeaturesFeatureSetBase198 const FeatureMap &getFeatures() const { return members; }
199 };
200
201 inline FeatureSetBase::FeatureSetBase() = default;
202 inline FeatureSetBase::~FeatureSetBase() = default;
203
204 } // namespace angle
205
206 #endif // ANGLE_PLATFORM_WORKAROUND_H_
207