1 // Copyright 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <string>
18 #include <map>
19 #include <vector>
20 
21 namespace gfxstream {
22 namespace host {
23 
24 struct FeatureInfo;
25 
26 using FeatureMap = std::map<std::string, FeatureInfo*>;
27 //type used for returning success or a string with the concatenated errors (missing features)
28 using FeatureResult = std::pair<bool, std::string>;
29 
30 struct FeatureInfo {
31     FeatureInfo(const FeatureInfo& rhs) = default;
32 
FeatureInfoFeatureInfo33     FeatureInfo(const char* name,
34                 const char* description,
35                 FeatureMap* map) :
36             name(name),
37             description(description),
38             enabled(false),
39             reason("Default value") {
40         if (map) {
41             (*map)[std::string(name)] = this;
42         }
43     }
44 
45     ~FeatureInfo() = default;
46 
47     std::string name;
48     std::string description;
49     bool enabled;
50     std::string reason;
51 };
52 
53 struct FeatureSet {
54     FeatureSet() = default;
55 
56     FeatureSet(const FeatureSet& rhs);
57     FeatureSet& operator=(const FeatureSet& rhs);
58 
59     FeatureMap map;
60 
61     FeatureInfo AsyncComposeSupport = {
62         "AsyncComposeSupport",
63         "If enabled, allows the guest to use asynchronous render control commands "
64         "to compose and post frame buffers.",
65         &map,
66     };
67     FeatureInfo ExternalBlob = {
68         "ExternalBlob",
69         "If enabled, virtio gpu blob resources will be allocated with external "
70         "memory and will be exportable via file descriptors.",
71         &map,
72     };
73     FeatureInfo VulkanExternalSync = {
74         "VulkanExternalSync",
75         "If enabled, Vulkan fences/semaphores will be allocated with external "
76         "create info and will be exportable via fence handles.",
77         &map,
78     };
79     FeatureInfo SystemBlob = {
80         "SystemBlob",
81         "If enabled, virtio gpu blob resources will be allocated with shmem and "
82         "will be exportable via file descriptors.",
83         &map,
84     };
85     FeatureInfo GlAsyncSwap = {
86         "GlAsyncSwap",
87         "If enabled, uses the host GL driver's fence commands and fence file "
88         "descriptors in the guest to have explicit signals of buffer swap "
89         "completion.",
90         &map,
91     };
92     FeatureInfo GlDirectMem = {
93         "GlDirectMem",
94         "If enabled, allows mapping the host address from glMapBufferRange() into "
95         "the guest.",
96         &map,
97     };
98     FeatureInfo GlDma = {
99         "GlDma",
100         "Default description: consider contributing a description if you see this!",
101         &map,
102     };
103     FeatureInfo GlDma2 = {
104         "GlDma2",
105         "Default description: consider contributing a description if you see this!",
106         &map,
107     };
108     FeatureInfo GlProgramBinaryLinkStatus = {
109         "GlProgramBinaryLinkStatus",
110         "If enabled, the host will track and report the correct link status of programs "
111         "created with glProgramBinary(). If not enabled, the host will effectively "
112         "return false for all glGetProgramiv(... GL_LINK_STATUS ...) calls."
113         ""
114         "Prior to aosp/3151743, the host GLES translator was not tracking the link "
115         "status of programs created by glProgramBinary() and would always return "
116         "false for glGetProgramiv(... GL_LINK_STATUS ...) calls."
117         ""
118         "Also, prior to aosp/3151743, the guest GL encoder was losing information about "
119         "`samplerExternalOES` between glGetProgramBinary() and glProgramBinary() calls "
120         "which would cause incorrect handling of sampling from a binding with "
121         "GL_TEXTURE_EXTERNAL_OES."
122         ""
123         "Guest applications seem to typically fallback to fully recreating programs "
124         "with shaders (glCreateShader() + glShaderSource() + glAttachShader()) when "
125         "linking fails with glProgramBinary(). This lead to backwards compatibility "
126         "problems when an old guest (which does not have the above guest GL encoder "
127         "fix) runs with a newer host (which does have the above host GLES translator "
128         "fix) as the fallback path would be disabled but the guest would have "
129         "incorrect GL_TEXTURE_EXTERNAL_OES handling. As such, the corrected host "
130         "behavior is hidden behind this feature.",
131         &map,
132     };
133     FeatureInfo GlPipeChecksum = {
134         "GlPipeChecksum",
135         "If enabled, the guest and host will use checksums to ensure consistency "
136         "for GL calls between the guest and host.",
137         &map,
138     };
139     FeatureInfo GlesDynamicVersion = {
140         "GlesDynamicVersion",
141         "If enabled, attempts to detect and use the maximum supported GLES version "
142         "from the host.",
143         &map,
144     };
145     FeatureInfo GrallocSync = {
146         "GrallocSync",
147         "If enabled, adds additional synchronization on the host for cases where "
148         "a guest app may directly writing to gralloc buffers and posting.",
149         &map,
150     };
151     FeatureInfo GuestVulkanOnly = {
152         "GuestVulkanOnly",
153         "If enabled, indicates that the guest only requires Vulkan translation. "
154         " The guest will not use GL and the host will not enable the GL backend. "
155         " This is the case when the guest uses libraries such as Angle or Zink for "
156         " GL to Vulkan translation.",
157         &map,
158     };
159     FeatureInfo HasSharedSlotsHostMemoryAllocator = {
160         "HasSharedSlotsHostMemoryAllocator",
161         "If enabled, the host supports "
162         "AddressSpaceSharedSlotsHostMemoryAllocatorContext.",
163         &map,
164     };
165     FeatureInfo HostComposition = {
166         "HostComposition",
167         "If enabled, the host supports composition via render control commands.",
168         &map,
169     };
170     FeatureInfo HwcMultiConfigs = {
171         "HwcMultiConfigs",
172         "If enabled, the host supports multiple HWComposer configs per display.",
173         &map,
174     };
175     FeatureInfo Minigbm = {
176         "Minigbm",
177         "If enabled, the guest is known to be using Minigbm as its Gralloc "
178         "implementation.",
179         &map,
180     };
181     FeatureInfo NativeTextureDecompression = {
182         "NativeTextureDecompression",
183         "If enabled, allows the host to use ASTC and ETC2 formats when supported by "
184         " the host GL driver.",
185         &map,
186     };
187     FeatureInfo NoDelayCloseColorBuffer = {
188         "NoDelayCloseColorBuffer",
189         "If enabled, indicates that the guest properly associates resources with "
190         "guest OS handles and that the host resources can be immediately cleaned "
191         "upon receiving resource clean up commands.",
192         &map,
193     };
194     FeatureInfo PlayStoreImage = {
195         "PlayStoreImage",
196         "If enabled, the guest image is using the play store image which has "
197         "additional requirements.",
198         &map,
199     };
200     FeatureInfo RefCountPipe = {
201         "RefCountPipe",
202         "If enabled, resources are referenced counted via a specific pipe "
203         "implementation.",
204         &map,
205     };
206     FeatureInfo VirtioGpuFenceContexts = {
207         "VirtioGpuFenceContexts",
208         "If enabled, the host will support multiple virtio gpu fence timelines.",
209         &map,
210     };
211     FeatureInfo VirtioGpuNativeSync = {
212         "VirtioGpuNativeSync",
213         "If enabled, use virtio gpu instead of goldfish sync for sync fd support.",
214         &map,
215     };
216     FeatureInfo VirtioGpuNext = {
217         "VirtioGpuNext",
218         "If enabled, virtio gpu supports blob resources (this was historically "
219         "called on a virtio-gpu-next branch in upstream kernel?).",
220         &map,
221     };
222     FeatureInfo BypassVulkanDeviceFeatureOverrides = {
223         "BypassVulkanDeviceFeatureOverrides",
224         "We are force disabling (overriding) some vulkan features (private data, uniform inline block etc) which the device may naturally support."
225         "If toggled ON, this flag will cause the host side to not force disable anything and let the device fully advertise supported features.",
226         &map,
227     };
228     FeatureInfo VulkanAllocateDeviceMemoryOnly = {
229         "VulkanAllocateDeviceMemoryOnly",
230         "If enabled, prevents the guest from allocating Vulkan memory that does "
231         "not have VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT.",
232         &map,
233     };
234     FeatureInfo VulkanAllocateHostMemory = {
235         "VulkanAllocateHostMemory",
236         "If enabled, allocates host private memory and uses "
237         "VK_EXT_external_memory_host to handle Vulkan "
238         "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT allocations.",
239         &map,
240     };
241     FeatureInfo VulkanBatchedDescriptorSetUpdate = {
242         "VulkanBatchedDescriptorSetUpdate",
243         "If enabled, Vulkan descriptor set updates via vkUpdateDescriptorSets() are "
244         "not immediately sent to the host and are instead deferred until needed "
245         "in vkQueueSubmit() commands.",
246         &map,
247     };
248     FeatureInfo VulkanIgnoredHandles = {
249         "VulkanIgnoredHandles",
250         "If enabled, the guest to host Vulkan protocol will ignore handles in some "
251         "cases such as VkWriteDescriptorSet().",
252         &map,
253     };
254     FeatureInfo VulkanNativeSwapchain = {
255         "VulkanNativeSwapchain",
256         "If enabled, the host display implementation uses a native Vulkan swapchain.",
257         &map,
258     };
259     FeatureInfo VulkanNullOptionalStrings = {
260         "VulkanNullOptionalStrings",
261         "If enabled, the guest to host Vulkan protocol will encode null optional "
262         "strings as actual null values instead of as empty strings.",
263         &map,
264     };
265     FeatureInfo VulkanQueueSubmitWithCommands = {
266         "VulkanQueueSubmitWithCommands",
267         "If enabled, uses deferred command submission with global sequence number "
268         "synchronization for Vulkan queue submits.",
269         &map,
270     };
271     FeatureInfo VulkanShaderFloat16Int8 = {
272         "VulkanShaderFloat16Int8",
273         "If enabled, enables the VK_KHR_shader_float16_int8 extension.",
274         &map,
275     };
276     FeatureInfo VulkanSnapshots = {
277         "VulkanSnapshots",
278         "If enabled, supports snapshotting the guest and host Vulkan state.",
279         &map,
280     };
281     FeatureInfo VulkanUseDedicatedAhbMemoryType = {
282         "VulkanUseDedicatedAhbMemoryType",
283         "If enabled, emulates an additional memory type for AHardwareBuffer allocations "
284         "that only has VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT for the purposes of preventing "
285         "the guest from trying to map AHardwareBuffer memory.",
286         &map,
287     };
288     FeatureInfo Vulkan = {
289         "Vulkan",
290         "If enabled, allows the guest to use Vulkan and enables the Vulkan backend "
291         "on the host.",
292         &map,
293     };
294     FeatureInfo Yuv420888ToNv21 = {
295         "Yuv420888ToNv21",
296         "If enabled, Androids HAL_PIXEL_FORMAT_YCbCr_420_888 format is treated as "
297         "NV21.",
298         &map,
299     };
300     FeatureInfo YuvCache = {
301         "YuvCache",
302         "If enabled, the host will cache YUV frames.",
303         &map,
304     };
305     FeatureInfo VulkanDebugUtils = {
306         "VulkanDebugUtils",
307         "If enabled, the host will enable VK_EXT_debug_utils extension when available to use "
308         "labels on Vulkan resources and operation",
309         &map,
310     };
311     FeatureInfo VulkanCommandBufferCheckpoints = {
312         "VulkanCommandBufferCheckpoints",
313         "If enabled, the host will enable the VK_NV_device_diagnostic_checkpoints extension "
314         "when available, track command buffers with markers, and report unfinished command "
315         "buffers on device lost. (TODO: VK_AMD_buffer_marker)",
316         &map,
317     };
318     FeatureInfo VulkanVirtualQueue = {
319         "VulkanVirtualQueue",
320         "(Experimental) If enabled, a virtual graphics queue will be added into physical Vulkan "
321         "device properties for the guest queries.",
322         &map,
323     };
324 };
325 struct FeatureDependencyHandler {
FeatureDependencyHandlerFeatureDependencyHandler326     FeatureDependencyHandler(const FeatureSet& set) : featureSetView(set){}
327     const FeatureSet& featureSetView;
328     const std::map<const FeatureInfo*, std::vector<const FeatureInfo*>> VK_FEATURE_DEPENDENCY_MAP= {
329         // List other dependencies here in the shape of:
330         // {FEATURE_X, {DEPENDENT_FEATURE_A, DEPENDENT_FEATURE_B}}
331         {&featureSetView.VulkanSnapshots, {&featureSetView.VulkanBatchedDescriptorSetUpdate, &featureSetView.Vulkan}},
332     };
333 
334     FeatureResult checkAllDependentFeaturesAreEnabled();
335 };
336 
337 #define GFXSTREAM_SET_FEATURE_ON_CONDITION(set, feature, condition) \
338     do                                                              \
339     {                                                               \
340         {                                                           \
341             (set)->feature.enabled = condition;                     \
342             (set)->feature.reason = #condition;                     \
343         }                                                           \
344     } while (0)
345 
346 }  // namespace host
347 }  // namespace gfxstream
348