1 // Copyright 2018 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 expresso or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include <GLES2/gl2.h> 17 #include <vulkan/vulkan.h> 18 19 #include <atomic> 20 #include <functional> 21 #include <memory> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <vector> 25 26 #include "BorrowedImageVk.h" 27 #include "CompositorVk.h" 28 #include "DebugUtilsHelper.h" 29 #include "DeviceLostHelper.h" 30 #include "DisplayVk.h" 31 #include "ExternalObjectManager.h" 32 #include "FrameworkFormats.h" 33 #include "aemu/base/Optional.h" 34 #include "aemu/base/ThreadAnnotations.h" 35 #include "gfxstream/host/BackendCallbacks.h" 36 #include "gfxstream/host/Features.h" 37 #include "goldfish_vk_private_defs.h" 38 #include "utils/GfxApiLogger.h" 39 #include "utils/RenderDoc.h" 40 41 #if defined(_WIN32) 42 typedef void* HANDLE; 43 // External sync objects are HANDLE on Windows 44 typedef HANDLE VK_EXT_SYNC_HANDLE; 45 // corresponds to INVALID_HANDLE_VALUE 46 #define VK_EXT_SYNC_HANDLE_INVALID (VK_EXT_SYNC_HANDLE)(uintptr_t)(-1) 47 #else 48 // External sync objects are fd's on other POSIX systems 49 typedef int VK_EXT_SYNC_HANDLE; 50 #define VK_EXT_SYNC_HANDLE_INVALID (-1) 51 #endif 52 53 namespace gfxstream { 54 namespace vk { 55 56 struct VulkanDispatch; 57 58 // Returns a consistent answer for which memory type index is best for staging 59 // memory. This is not the simplest thing in the world because even if a memory 60 // type index is host visible, that doesn't mean a VkBuffer is allowed to be 61 // associated with it. 62 bool getStagingMemoryTypeIndex(VulkanDispatch* vk, VkDevice device, 63 const VkPhysicalDeviceMemoryProperties* memProps, 64 uint32_t* typeIndex); 65 66 enum class AstcEmulationMode { 67 Disabled, // No ASTC emulation (ie: ASTC not supported unless the GPU supports it natively) 68 Cpu, // Decompress ASTC textures on the CPU 69 Gpu, // Decompress ASTC textures on the GPU 70 }; 71 72 // Global state that holds a global Vulkan instance along with globally 73 // exported memory allocations + images. This is in order to service things 74 // like AndroidHardwareBuffer/FuchsiaImagePipeHandle. Each such allocation is 75 // associated with a ColorBuffer handle, and depending on host-side support for 76 // GL_EXT_memory_object, also be able to zero-copy render into and readback 77 // with the traditional GL pipeline. 78 class VkEmulation { 79 public: 80 ~VkEmulation(); 81 82 static std::unique_ptr<VkEmulation> create(VulkanDispatch* vk, 83 gfxstream::host::BackendCallbacks callbacks, 84 gfxstream::host::FeatureSet features); 85 86 struct Features { 87 bool glInteropSupported = false; 88 bool deferredCommands = false; 89 bool createResourceWithRequirements = false; 90 bool useVulkanComposition = false; 91 bool useVulkanNativeSwapchain = false; 92 std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> guestRenderDoc = nullptr; 93 AstcEmulationMode astcLdrEmulationMode = AstcEmulationMode::Disabled; 94 bool enableEtc2Emulation = false; 95 bool enableYcbcrEmulation = false; 96 bool guestVulkanOnly = false; 97 bool useDedicatedAllocations = false; 98 }; 99 void initFeatures(Features features); 100 101 bool isYcbcrEmulationEnabled() const; 102 103 bool isEtc2EmulationEnabled() const; 104 105 bool deferredCommandsEnabled() const; 106 bool createResourcesWithRequirementsEnabled() const; 107 108 bool supportsExternalMemoryCapabilities() const; 109 bool supportsExternalSemaphoreCapabilities() const; 110 bool supportsExternalFenceCapabilities() const; 111 bool supportsSurfaces() const; 112 bool supportsMoltenVk() const; 113 114 bool supportsGetPhysicalDeviceProperties2() const; 115 116 bool supportsPhysicalDeviceIDProperties() const; 117 118 std::optional<std::array<uint8_t, VK_UUID_SIZE>> getDeviceUuid(); 119 std::optional<std::array<uint8_t, VK_UUID_SIZE>> getDriverUuid(); 120 121 bool supportsPrivateData() const; 122 123 bool supportsExternalMemoryImport() const; 124 125 bool supportsDmaBuf() const; 126 127 bool supportsExternalMemoryHostProperties() const; 128 129 std::optional<VkPhysicalDeviceRobustness2FeaturesEXT> getRobustness2Features() const; 130 131 VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties() const; 132 133 bool isGuestVulkanOnly() const; 134 135 bool commandBufferCheckpointsEnabled() const; 136 137 bool supportsSamplerYcbcrConversion() const; 138 139 bool debugUtilsEnabled() const; 140 141 DebugUtilsHelper& getDebugUtilsHelper(); 142 143 DeviceLostHelper& getDeviceLostHelper(); 144 145 const gfxstream::host::FeatureSet& getFeatures() const; 146 147 const gfxstream::host::BackendCallbacks& getCallbacks() const; 148 149 AstcEmulationMode getAstcLdrEmulationMode() const; 150 151 emugl::RenderDocWithMultipleVkInstances* getRenderDoc(); 152 153 Compositor* getCompositor(); 154 155 DisplayVk* getDisplay(); 156 157 VkInstance getInstance(); 158 159 std::string getGpuVendor() const; 160 std::string getGpuName() const; 161 std::string getGpuVersionString() const; 162 std::string getInstanceExtensionsString() const; 163 std::string getDeviceExtensionsString() const; 164 165 const VkPhysicalDeviceProperties getPhysicalDeviceProperties() const; 166 167 struct RepresentativeColorBufferMemoryTypeInfo { 168 // The host memory type index used for Buffer/ColorBuffer allocations. 169 uint32_t hostMemoryTypeIndex; 170 171 // The guest memory type index that will be returned to guest processes querying 172 // the memory type index of host AHardwareBuffer/ColorBuffer allocations. This may 173 // point to an emulated memory type so that the host can control which memory flags are 174 // exposed to the guest (i.e. hide VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT from the guest). 175 uint32_t guestMemoryTypeIndex; 176 }; 177 RepresentativeColorBufferMemoryTypeInfo getRepresentativeColorBufferMemoryTypeInfo() const; 178 179 void onVkDeviceLost(); 180 181 VkExternalMemoryHandleTypeFlagBits getDefaultExternalMemoryHandleType(); 182 183 std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window, 184 uint32_t width, 185 uint32_t height); 186 187 // ColorBuffer operations 188 189 bool getColorBufferShareInfo(uint32_t colorBufferHandle, bool* glExported, 190 bool* externalMemoryCompatible); 191 192 bool getColorBufferAllocationInfo(uint32_t colorBufferHandle, VkDeviceSize* outSize, 193 uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc, 194 void** outMappedPtr); 195 196 std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo(VkFormat format, 197 uint32_t width, 198 uint32_t height, 199 VkImageTiling tiling); 200 201 bool isFormatSupported(GLenum format); 202 203 bool createVkColorBuffer(uint32_t width, uint32_t height, GLenum format, 204 FrameworkFormat frameworkFormat, uint32_t colorBufferHandle, 205 bool vulkanOnly, uint32_t memoryProperty); 206 207 bool teardownVkColorBuffer(uint32_t colorBufferHandle); 208 209 struct ExternalMemoryInfo { 210 // Input fields 211 VkDeviceSize size; 212 uint32_t typeIndex; 213 214 // Output fields 215 uint32_t id = 0; 216 VkDeviceMemory memory = VK_NULL_HANDLE; 217 218 // host-mapping fields 219 // host virtual address (hva). 220 void* mappedPtr = nullptr; 221 // host virtual address, aligned to 4KB page. 222 void* pageAlignedHva = nullptr; 223 // the offset of |mappedPtr| off its memory page. 224 uint32_t pageOffset = 0u; 225 // the offset set in |vkBindImageMemory| or |vkBindBufferMemory|. 226 uint32_t bindOffset = 0u; 227 // the size of all the pages the memory uses. 228 size_t sizeToPage = 0u; 229 // guest physical address. 230 uintptr_t gpa = 0u; 231 232 std::optional<ExternalHandleInfo> handleInfo = std::nullopt; 233 #ifdef __APPLE__ 234 // This is used as an external handle when MoltenVK is enabled 235 MTLResource_id externalMetalHandle = nullptr; 236 #endif 237 238 bool dedicatedAllocation = false; 239 }; 240 241 bool allocExternalMemory( 242 VulkanDispatch* vk, ExternalMemoryInfo* info, bool actuallyExternal = true, 243 android::base::Optional<uint64_t> deviceAlignment = android::base::kNullopt, 244 android::base::Optional<VkBuffer> bufferForDedicatedAllocation = android::base::kNullopt, 245 android::base::Optional<VkImage> imageForDedicatedAllocation = android::base::kNullopt); 246 247 bool importExternalMemory(VulkanDispatch* vk, VkDevice targetDevice, 248 const ExternalMemoryInfo* info, 249 VkMemoryDedicatedAllocateInfo* dedicatedAllocInfo, 250 VkDeviceMemory* out); 251 252 enum class VulkanMode { 253 // Default: ColorBuffers can still be used with the existing GL-based 254 // API. Synchronization with (if it exists) Vulkan images happens on 255 // every one of the GL-based API calls: 256 // 257 // rcReadColorBuffer 258 // rcUpdateColorBuffer 259 // rcBindTexture 260 // rcBindRenderbuffer 261 // rcFlushWindowColorBuffer 262 // 263 // either through explicit CPU copies or implicit in the host driver 264 // if OpenGL interop is supported. 265 // 266 // When images are posted (rcFBPost), 267 // eglSwapBuffers is used, even if that requires a CPU readback. 268 269 Default = 0, 270 271 // VulkanOnly: It is assumed that the guest interacts entirely with 272 // the underlying Vulkan image in the guest and does not use the 273 // GL-based API. This means we can assume those APIs are not called: 274 // 275 // rcReadColorBuffer 276 // rcUpdateColorBuffer 277 // rcBindTexture 278 // rcBindRenderbuffer 279 // rcFlushWindowColorBuffer 280 // 281 // and thus we skip a lot of GL/Vk synchronization. 282 // 283 // When images are posted, eglSwapBuffers is only used if OpenGL 284 // interop is supported. If OpenGL interop is not supported, then we 285 // use a host platform-specific Vulkan swapchain to display the 286 // results. 287 288 VulkanOnly = 1, 289 }; 290 291 struct ColorBufferInfo { 292 ExternalMemoryInfo memory; 293 294 uint32_t handle; 295 296 /* Set in create(), before initialize() */ 297 uint32_t width; 298 uint32_t height; 299 GLenum internalFormat; 300 uint32_t memoryProperty; 301 int frameworkFormat; 302 int frameworkStride; 303 bool initialized = false; 304 305 VkImage image = VK_NULL_HANDLE; 306 VkImageView imageView = VK_NULL_HANDLE; 307 VkSamplerYcbcrConversion ycbcrConversion = VK_NULL_HANDLE; 308 VkImageCreateInfo imageCreateInfoShallow = {}; 309 310 VkImageLayout currentLayout = VK_IMAGE_LAYOUT_UNDEFINED; 311 uint32_t currentQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL; 312 313 bool glExported = false; 314 bool externalMemoryCompatible = false; 315 316 VulkanMode vulkanMode = VulkanMode::Default; 317 }; 318 std::optional<VkEmulation::ColorBufferInfo> getColorBufferInfo(uint32_t colorBufferHandle); 319 320 struct BufferInfo { 321 ExternalMemoryInfo memory; 322 uint32_t handle; 323 324 VkDeviceSize size; 325 VkBufferCreateFlags createFlags; 326 VkBufferUsageFlags usageFlags; 327 VkSharingMode sharingMode; 328 329 VkBuffer buffer = VK_NULL_HANDLE; 330 331 bool glExported = false; 332 VulkanMode vulkanMode = VulkanMode::Default; 333 }; 334 335 std::optional<ExternalHandleInfo> dupColorBufferExtMemoryHandle(uint32_t colorBufferHandle); 336 #ifdef __APPLE__ 337 MTLResource_id getColorBufferMetalMemoryHandle(uint32_t colorBufferHandle); 338 VkImage getColorBufferVkImage(uint32_t colorBufferHandle); 339 #endif 340 341 struct VkColorBufferMemoryExport { 342 ExternalHandleInfo handleInfo; 343 uint64_t size = 0; 344 bool linearTiling = false; 345 bool dedicatedAllocation = false; 346 }; 347 std::optional<VkColorBufferMemoryExport> exportColorBufferMemory(uint32_t colorBufferHandle); 348 349 bool setColorBufferVulkanMode(uint32_t colorBufferHandle, uint32_t vulkanMode); 350 int32_t mapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa, uint64_t size = 0); 351 352 bool colorBufferNeedsUpdateBetweenGlAndVk(uint32_t colorBufferHandle); 353 354 bool readColorBufferToBytes(uint32_t colorBufferHandle, std::vector<uint8_t>* bytes); 355 bool readColorBufferToBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w, 356 uint32_t h, void* outPixels, uint64_t outPixelsSize); 357 358 bool updateColorBufferFromBytes(uint32_t colorBufferHandle, const std::vector<uint8_t>& bytes); 359 bool updateColorBufferFromBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w, 360 uint32_t h, const void* pixels); 361 362 // Data buffer operations 363 bool getBufferAllocationInfo(uint32_t bufferHandle, VkDeviceSize* outSize, 364 uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc); 365 366 bool setupVkBuffer(uint64_t size, uint32_t bufferHandle, bool vulkanOnly = false, 367 uint32_t memoryProperty = 0); 368 bool teardownVkBuffer(uint32_t bufferHandle); 369 370 std::optional<GenericDescriptorInfo> exportMemoryHandle(VkDevice device, VkDeviceMemory memory); 371 std::optional<ExternalHandleInfo> dupBufferExtMemoryHandle(uint32_t bufferHandle); 372 #ifdef __APPLE__ 373 MTLResource_id getBufferMetalMemoryHandle(uint32_t bufferHandle); 374 MTLResource_id getMtlResourceFromVkDeviceMemory(VulkanDispatch* vk, VkDeviceMemory memory); 375 #endif 376 377 bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes); 378 bool updateBufferFromBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, 379 const void* bytes); 380 381 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_tohost( 382 VkExternalMemoryHandleTypeFlags bits); 383 384 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_fromhost( 385 VkExternalMemoryHandleTypeFlags hostBits, 386 VkExternalMemoryHandleTypeFlags wantedGuestHandleType); 387 388 VkExternalMemoryProperties transformExternalMemoryProperties_tohost( 389 VkExternalMemoryProperties props); 390 391 VkExternalMemoryProperties transformExternalMemoryProperties_fromhost( 392 VkExternalMemoryProperties props, VkExternalMemoryHandleTypeFlags wantedGuestHandleType); 393 394 void setColorBufferCurrentLayout(uint32_t colorBufferHandle, VkImageLayout); 395 396 VkImageLayout getColorBufferCurrentLayout(uint32_t colorBufferHandle); 397 398 void releaseColorBufferForGuestUse(uint32_t colorBufferHandle); 399 400 std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForComposition(uint32_t colorBufferHandle, 401 bool colorBufferIsTarget); 402 std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForDisplay(uint32_t colorBufferHandle); 403 404 private: 405 VkEmulation() = default; 406 407 std::optional<RepresentativeColorBufferMemoryTypeInfo> 408 findRepresentativeColorBufferMemoryTypeIndexLocked() REQUIRES(mMutex); 409 410 struct ImageSupportInfo { 411 // Input parameters 412 VkFormat format; 413 VkImageType type; 414 VkImageTiling tiling; 415 VkImageUsageFlags usageFlags; 416 VkImageCreateFlags createFlags; 417 418 // Output parameters 419 bool supported = false; 420 bool supportsExternalMemory = false; 421 bool requiresDedicatedAllocation = false; 422 423 // Keep the raw output around. 424 VkFormatProperties2 formatProps2; 425 VkImageFormatProperties2 imageFormatProps2; 426 VkExternalImageFormatProperties extFormatProps; 427 }; 428 429 static std::vector<VkEmulation::ImageSupportInfo> getBasicImageSupportList(); 430 431 // For a given ImageSupportInfo, populates usageWithExternalHandles and 432 // requiresDedicatedAllocation. memoryTypeBits are populated later once the 433 // device is created, because that needs a test image to be created. 434 // If we don't support external memory, it's assumed dedicated allocations are 435 // not needed. 436 // Precondition: sVkEmulation instance has been created and ext memory caps known. 437 // Returns false if the query failed. 438 bool populateImageFormatExternalMemorySupportInfo(VulkanDispatch* vk, VkPhysicalDevice physdev, 439 ImageSupportInfo* info); 440 441 struct DeviceSupportInfo { 442 bool hasGraphicsQueueFamily = false; 443 bool hasComputeQueueFamily = false; 444 bool supportsExternalMemoryImport = false; 445 bool supportsExternalMemoryExport = false; 446 bool supportsDmaBuf = false; 447 bool supportsDriverProperties = false; 448 bool supportsExternalMemoryHostProps = false; 449 bool hasSamplerYcbcrConversionExtension = false; 450 bool supportsSamplerYcbcrConversion = false; 451 bool glInteropSupported = false; 452 bool hasNvidiaDeviceDiagnosticCheckpointsExtension = false; 453 bool supportsNvidiaDeviceDiagnosticCheckpoints = false; 454 bool supportsPrivateData = false; 455 456 std::vector<VkExtensionProperties> extensions; 457 458 std::vector<uint32_t> graphicsQueueFamilyIndices; 459 std::vector<uint32_t> computeQueueFamilyIndices; 460 461 VkPhysicalDeviceProperties physdevProps; 462 VkPhysicalDeviceMemoryProperties memProps; 463 VkPhysicalDeviceIDPropertiesKHR idProps; 464 VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProps; 465 466 std::string driverVendor; 467 std::string driverVersion; 468 469 PFN_vkGetImageMemoryRequirements2KHR getImageMemoryRequirements2Func = nullptr; 470 PFN_vkGetBufferMemoryRequirements2KHR getBufferMemoryRequirements2Func = nullptr; 471 472 #ifdef _WIN32 473 PFN_vkGetMemoryWin32HandleKHR getMemoryHandleFunc = nullptr; 474 #else 475 PFN_vkGetMemoryFdKHR getMemoryHandleFunc = nullptr; 476 #endif 477 478 // Set only if requested and supported 479 std::optional<VkPhysicalDeviceRobustness2FeaturesEXT> robustness2Features; 480 }; 481 482 uint32_t getValidMemoryTypeIndex(uint32_t requiredMemoryTypeBits, 483 VkMemoryPropertyFlags memoryProperty = 0); 484 485 int getSelectedGpuIndex(const std::vector<DeviceSupportInfo>& deviceInfos); 486 487 bool isFormatVulkanCompatible(GLenum internalFormat); 488 489 bool getColorBufferAllocationInfoLocked(uint32_t colorBufferHandle, VkDeviceSize* outSize, 490 uint32_t* outMemoryTypeIndex, 491 bool* outMemoryIsDedicatedAlloc, void** outMappedPtr) REQUIRES(mMutex); 492 493 std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfoLocked( 494 VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling) REQUIRES(mMutex); 495 496 bool createVkColorBufferLocked(uint32_t width, uint32_t height, GLenum internalFormat, 497 FrameworkFormat frameworkFormat, uint32_t colorBufferHandle, 498 bool vulkanOnly, uint32_t memoryProperty) REQUIRES(mMutex); 499 500 bool teardownVkColorBufferLocked(uint32_t colorBufferHandle) REQUIRES(mMutex); 501 502 bool colorBufferNeedsUpdateBetweenGlAndVk(const VkEmulation::ColorBufferInfo& colorBufferInfo); 503 504 bool readColorBufferToBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y, 505 uint32_t w, uint32_t h, void* outPixels, 506 uint64_t outPixelsSize) REQUIRES(mMutex); 507 508 bool updateColorBufferFromBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y, 509 uint32_t w, uint32_t h, const void* pixels, 510 size_t inputPixelsSize) REQUIRES(mMutex); 511 512 bool updateMemReqsForExtMem(std::optional<ExternalHandleInfo> extMemHandleInfo, 513 VkMemoryRequirements* pMemReqs); 514 515 std::tuple<VkCommandBuffer, VkFence> allocateQueueTransferCommandBufferLocked() REQUIRES(mMutex); 516 517 void freeExternalMemoryLocked(VulkanDispatch* vk, ExternalMemoryInfo* info) REQUIRES(mMutex); 518 519 std::mutex mMutex; 520 521 gfxstream::host::BackendCallbacks mCallbacks; 522 523 gfxstream::host::FeatureSet mFeatures; 524 525 RepresentativeColorBufferMemoryTypeInfo mRepresentativeColorBufferMemoryTypeInfo; 526 527 // Whether to use deferred command submission. 528 bool mUseDeferredCommands = false; 529 530 // Whether to fuse memory requirements getting with resource creation. 531 bool mUseCreateResourcesWithRequirements = false; 532 533 // RenderDoc integration for guest VkInstances. 534 std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> mGuestRenderDoc; 535 536 // Whether to use ASTC emulation. Our current ASTC decoder implementation may lead to device 537 // lost on certain device on Windows. 538 AstcEmulationMode mAstcLdrEmulationMode = AstcEmulationMode::Disabled; 539 540 // Whether to use ETC2 emulation. 541 bool mEnableEtc2Emulation = false; 542 543 // Whether to use Ycbcr emulation. If this feature is turned on, Ycbcr request will always use 544 // the emulation path regardless of whether the host Vulkan driver actually supports Ycbcr 545 // conversion or not. 546 bool mEnableYcbcrEmulation = false; 547 548 bool mGuestVulkanOnly = false; 549 550 bool mUseDedicatedAllocations = false; 551 552 // Instance and device for creating the system-wide shareable objects. 553 VkInstance mInstance = VK_NULL_HANDLE; 554 uint32_t mVulkanInstanceVersion = 0; 555 std::vector<VkExtensionProperties> mInstanceExtensions; 556 557 uint32_t mPhysicalDeviceIndex = 0; 558 VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE; 559 560 VkDevice mDevice = VK_NULL_HANDLE; 561 562 // Global, instance and device dispatch tables. 563 VulkanDispatch* mGvk = nullptr; 564 VulkanDispatch* mIvk = nullptr; 565 VulkanDispatch* mDvk = nullptr; 566 567 bool mInstanceSupportsPhysicalDeviceIDProperties = false; 568 bool mInstanceSupportsGetPhysicalDeviceProperties2 = false; 569 bool mInstanceSupportsExternalMemoryCapabilities = false; 570 bool mInstanceSupportsExternalSemaphoreCapabilities = false; 571 bool mInstanceSupportsExternalFenceCapabilities = false; 572 bool mInstanceSupportsSurface = false; 573 #if defined(__APPLE__) 574 bool mInstanceSupportsMoltenVK = false; 575 #else 576 static const bool mInstanceSupportsMoltenVK = false; 577 #endif 578 579 PFN_vkGetPhysicalDeviceImageFormatProperties2KHR mGetImageFormatProperties2Func = nullptr; 580 PFN_vkGetPhysicalDeviceProperties2KHR mGetPhysicalDeviceProperties2Func = nullptr; 581 PFN_vkGetPhysicalDeviceFeatures2 mGetPhysicalDeviceFeatures2Func = nullptr; 582 583 bool mDebugUtilsAvailableAndRequested = false; 584 DebugUtilsHelper mDebugUtilsHelper = DebugUtilsHelper::withUtilsDisabled(); 585 586 bool mCommandBufferCheckpointsSupportedAndRequested = false; 587 DeviceLostHelper mDeviceLostHelper{}; 588 589 // Queue, command pool, and command buffer 590 // for running commands to sync stuff system-wide. 591 // TODO(b/197362803): Encapsulate host side VkQueue and the lock. 592 VkQueue mQueue = VK_NULL_HANDLE; 593 std::shared_ptr<android::base::Lock> mQueueLock = nullptr; 594 uint32_t mQueueFamilyIndex = 0; 595 596 VkCommandPool mCommandPool = VK_NULL_HANDLE; 597 VkCommandBuffer mCommandBuffer = VK_NULL_HANDLE; 598 VkFence mCommandBufferFence = VK_NULL_HANDLE; 599 600 std::vector<ImageSupportInfo> mImageSupportInfo; 601 602 // 128 mb staging buffer (really, just a few 4K frames or one 4k HDR frame) 603 // ought to be big enough for anybody! 604 static constexpr VkDeviceSize kDefaultStagingBufferSize = 128ULL * 1048576ULL; 605 606 struct StagingBufferInfo { 607 // TODO: Don't actually use this as external memory until host visible 608 // external is supported on all platforms 609 ExternalMemoryInfo memory; 610 VkBuffer buffer = VK_NULL_HANDLE; 611 VkDeviceSize size = kDefaultStagingBufferSize; 612 }; 613 614 // Track what is supported on whatever device was selected. 615 DeviceSupportInfo mDeviceInfo; 616 617 // A single staging buffer to perform most transfers to/from OpenGL on the 618 // host. It is shareable across instances. The memory is shareable but the 619 // buffer is not; other users need to create buffers that 620 // bind to imported versions of the memory. 621 StagingBufferInfo mStaging GUARDED_BY(mMutex); 622 623 // ColorBuffers are intended to back the guest's shareable images. 624 // For example: 625 // Android: gralloc 626 // Fuchsia: ImagePipeHandle 627 // Linux: dmabuf 628 std::unordered_map<uint32_t, ColorBufferInfo> mColorBuffers GUARDED_BY(mMutex); 629 630 // Buffers are intended to back the guest's shareable Vulkan buffers. 631 std::unordered_map<uint32_t, BufferInfo> mBuffers GUARDED_BY(mMutex); 632 633 // In order to support VK_KHR_external_memory_(fd|win32) we need also to 634 // support the concept of plain external memories that are just memory and 635 // not necessarily images. These are then intended to pass through to the 636 // guest in some way, with 1:1 mapping between guest and host external 637 // memory handles. 638 std::unordered_map<uint32_t, ExternalMemoryInfo> mExternalMemories GUARDED_BY(mMutex); 639 640 // The host keeps a set of occupied guest memory addresses to avoid a 641 // host memory address mapped to guest twice. 642 std::unordered_set<uint64_t> mOccupiedGpas GUARDED_BY(mMutex); 643 644 // We can also consider using a single external memory object to back all 645 // host visible allocations in the guest. This would save memory, but we 646 // would also need to automatically add 647 // VkExternalMemory(Image|Buffer)CreateInfo, or if it is already there, OR 648 // it with the handle types on the host. 649 // A rough sketch: Some memories/images/buffers in the guest 650 // are backed by host visible memory: 651 // There is already a virtual memory type for those things in the current 652 // implementation. The guest doesn't know whether the pointer or the 653 // VkDeviceMemory object is backed by host external or non external. 654 // TODO: are all possible buffer / image usages compatible with 655 // external backing? 656 // TODO: try switching to this 657 ExternalMemoryInfo mVirtualHostVisibleHeap; 658 659 // Every command buffer in the pool is associated with a VkFence which is 660 // signaled only if the command buffer completes. 661 std::vector<std::tuple<VkCommandBuffer, VkFence>> mTransferQueueCommandBufferPool GUARDED_BY(mMutex); 662 663 std::unique_ptr<CompositorVk> mCompositorVk; 664 665 // The implementation for Vulkan native swapchain. Only initialized in initVkEmulationFeatures 666 // if useVulkanNativeSwapchain is set. 667 std::unique_ptr<DisplayVk> mDisplayVk; 668 }; 669 670 } // namespace vk 671 } // namespace gfxstream 672