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