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 "DisplayVk.h" 30 #include "FrameworkFormats.h" 31 #include "aemu/base/ManagedDescriptor.hpp" 32 #include "aemu/base/Optional.h" 33 #include "aemu/base/synchronization/Lock.h" 34 #include "gfxstream/host/Features.h" 35 #include "goldfish_vk_private_defs.h" 36 #include "utils/GfxApiLogger.h" 37 #include "utils/RenderDoc.h" 38 39 #ifdef _WIN32 40 typedef void* HANDLE; 41 #endif 42 43 #if defined(_WIN32) 44 // External sync objects are HANDLE on Windows 45 typedef HANDLE VK_EXT_SYNC_HANDLE; 46 // corresponds to INVALID_HANDLE_VALUE 47 #define VK_EXT_SYNC_HANDLE_INVALID (VK_EXT_SYNC_HANDLE)(uintptr_t)(-1) 48 #else 49 // External sync objects are fd's on other POSIX systems 50 typedef int VK_EXT_SYNC_HANDLE; 51 #define VK_EXT_SYNC_HANDLE_INVALID (-1) 52 #endif 53 54 #if defined(_WIN32) 55 // External memory objects are HANDLE on Windows 56 typedef HANDLE VK_EXT_MEMORY_HANDLE; 57 // corresponds to INVALID_HANDLE_VALUE 58 #define VK_EXT_MEMORY_HANDLE_INVALID (VK_EXT_MEMORY_HANDLE)(uintptr_t)(-1) 59 #define VK_EXT_MEMORY_HANDLE_TYPE_BIT VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT 60 #elif defined(__QNX__) 61 #include <screen/screen.h> 62 // External memory objects are screen_buffer_t handles on QNX 63 typedef screen_buffer_t VK_EXT_MEMORY_HANDLE; 64 #define VK_EXT_MEMORY_HANDLE_INVALID (VK_EXT_MEMORY_HANDLE) nullptr 65 #define VK_EXT_MEMORY_HANDLE_TYPE_BIT VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX 66 #else 67 // External memory objects are fd's on other POSIX systems 68 typedef int VK_EXT_MEMORY_HANDLE; 69 #define VK_EXT_MEMORY_HANDLE_INVALID (-1) 70 #define VK_EXT_MEMORY_HANDLE_TYPE_BIT VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT 71 #endif 72 73 namespace gfxstream { 74 namespace vk { 75 76 struct VulkanDispatch; 77 78 // Returns a consistent answer for which memory type index is best for staging 79 // memory. This is not the simplest thing in the world because even if a memory 80 // type index is host visible, that doesn't mean a VkBuffer is allowed to be 81 // associated with it. 82 bool getStagingMemoryTypeIndex(VulkanDispatch* vk, VkDevice device, 83 const VkPhysicalDeviceMemoryProperties* memProps, 84 uint32_t* typeIndex); 85 86 87 VK_EXT_MEMORY_HANDLE dupExternalMemory(VK_EXT_MEMORY_HANDLE); 88 89 enum class AstcEmulationMode { 90 Disabled, // No ASTC emulation (ie: ASTC not supported unless the GPU supports it natively) 91 Cpu, // Decompress ASTC textures on the CPU 92 Gpu, // Decompress ASTC textures on the GPU 93 }; 94 95 // Global state that holds a global Vulkan instance along with globally 96 // exported memory allocations + images. This is in order to service things 97 // like AndroidHardwareBuffer/FuchsiaImagePipeHandle. Each such allocation is 98 // associated with a ColorBuffer handle, and depending on host-side support for 99 // GL_EXT_memory_object, also be able to zero-copy render into and readback 100 // with the traditional GL pipeline. 101 struct VkEmulation { 102 // Whether initialization succeeded. 103 bool live = false; 104 105 gfxstream::host::FeatureSet features; 106 107 // Whether to use deferred command submission. 108 bool useDeferredCommands = false; 109 110 // Whether to fuse memory requirements getting with resource creation. 111 bool useCreateResourcesWithRequirements = false; 112 113 // RenderDoc integration for guest VkInstances. 114 std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> guestRenderDoc = nullptr; 115 116 // Whether to use ASTC emulation. Our current ASTC decoder implementation may lead to device 117 // lost on certain device on Windows. 118 AstcEmulationMode astcLdrEmulationMode = AstcEmulationMode::Disabled; 119 120 // Whether to use ETC2 emulation. 121 bool enableEtc2Emulation = false; 122 123 // Whether to use Ycbcr emulation. If this feature is turned on, Ycbcr request will always use 124 // the emulation path regardless of whether the host Vulkan driver actually supports Ycbcr 125 // conversion or not. 126 bool enableYcbcrEmulation = false; 127 128 bool guestUsesAngle = false; 129 130 bool useDedicatedAllocations = false; 131 132 // Instance and device for creating the system-wide shareable objects. 133 VkInstance instance = VK_NULL_HANDLE; 134 VkPhysicalDevice physdev = VK_NULL_HANDLE; 135 VkDevice device = VK_NULL_HANDLE; 136 137 // Physical device index 138 uint32_t physicalDeviceIndex = 0; 139 140 // Global, instance and device dispatch tables. 141 VulkanDispatch* gvk = nullptr; 142 VulkanDispatch* ivk = nullptr; 143 VulkanDispatch* dvk = nullptr; 144 145 bool instanceSupportsExternalMemoryCapabilities = false; 146 bool instanceSupportsExternalSemaphoreCapabilities = false; 147 bool instanceSupportsSurface = false; 148 PFN_vkGetPhysicalDeviceImageFormatProperties2KHR getImageFormatProperties2Func = nullptr; 149 PFN_vkGetPhysicalDeviceProperties2KHR getPhysicalDeviceProperties2Func = nullptr; 150 PFN_vkGetPhysicalDeviceFeatures2 getPhysicalDeviceFeatures2Func = nullptr; 151 152 #if defined(__APPLE__) && defined(VK_MVK_moltenvk) 153 bool instanceSupportsMoltenVK = false; 154 PFN_vkSetMTLTextureMVK setMTLTextureFunc = nullptr; 155 PFN_vkGetMTLTextureMVK getMTLTextureFunc = nullptr; 156 #else 157 static const bool instanceSupportsMoltenVK = false; 158 #endif 159 160 bool debugUtilsAvailableAndRequested = false; 161 DebugUtilsHelper debugUtilsHelper = DebugUtilsHelper::withUtilsDisabled(); 162 163 // Queue, command pool, and command buffer 164 // for running commands to sync stuff system-wide. 165 // TODO(b/197362803): Encapsulate host side VkQueue and the lock. 166 VkQueue queue = VK_NULL_HANDLE; 167 std::shared_ptr<android::base::Lock> queueLock = nullptr; 168 uint32_t queueFamilyIndex = 0; 169 VkCommandPool commandPool = VK_NULL_HANDLE; 170 VkCommandBuffer commandBuffer = VK_NULL_HANDLE; 171 VkFence commandBufferFence = VK_NULL_HANDLE; 172 173 struct ImageSupportInfo { 174 // Input parameters 175 VkFormat format; 176 VkImageType type; 177 VkImageTiling tiling; 178 VkImageUsageFlags usageFlags; 179 VkImageCreateFlags createFlags; 180 181 // Output parameters 182 bool supported = false; 183 bool supportsExternalMemory = false; 184 bool requiresDedicatedAllocation = false; 185 186 // Keep the raw output around. 187 VkFormatProperties2 formatProps2; 188 VkImageFormatProperties2 imageFormatProps2; 189 VkExternalImageFormatProperties extFormatProps; 190 191 // Populated later when device is available. 192 uint32_t memoryTypeBits = 0; 193 bool memoryTypeBitsKnown = false; 194 }; 195 196 std::vector<ImageSupportInfo> imageSupportInfo; 197 198 struct DeviceSupportInfo { 199 bool hasGraphicsQueueFamily = false; 200 bool hasComputeQueueFamily = false; 201 bool supportsExternalMemoryImport = false; 202 bool supportsExternalMemoryExport = false; 203 bool supportsIdProperties = false; 204 bool supportsDriverProperties = false; 205 bool hasSamplerYcbcrConversionExtension = false; 206 bool supportsSamplerYcbcrConversion = false; 207 bool glInteropSupported = false; 208 209 std::vector<VkExtensionProperties> extensions; 210 211 std::vector<uint32_t> graphicsQueueFamilyIndices; 212 std::vector<uint32_t> computeQueueFamilyIndices; 213 214 VkPhysicalDeviceProperties physdevProps; 215 VkPhysicalDeviceMemoryProperties memProps; 216 VkPhysicalDeviceIDPropertiesKHR idProps; 217 218 std::string driverVendor; 219 std::string driverVersion; 220 221 PFN_vkGetImageMemoryRequirements2KHR getImageMemoryRequirements2Func = nullptr; 222 PFN_vkGetBufferMemoryRequirements2KHR getBufferMemoryRequirements2Func = nullptr; 223 224 #ifdef _WIN32 225 PFN_vkGetMemoryWin32HandleKHR getMemoryHandleFunc = nullptr; 226 #else 227 PFN_vkGetMemoryFdKHR getMemoryHandleFunc = nullptr; 228 #endif 229 }; 230 231 struct ExternalMemoryInfo { 232 // Input fields 233 VkDeviceSize size; 234 uint32_t typeIndex; 235 236 // Output fields 237 uint32_t id = 0; 238 VkDeviceMemory memory = VK_NULL_HANDLE; 239 240 // host-mapping fields 241 // host virtual address (hva). 242 void* mappedPtr = nullptr; 243 // host virtual address, aligned to 4KB page. 244 void* pageAlignedHva = nullptr; 245 // the offset of |mappedPtr| off its memory page. 246 uint32_t pageOffset = 0u; 247 // the offset set in |vkBindImageMemory| or |vkBindBufferMemory|. 248 uint32_t bindOffset = 0u; 249 // the size of all the pages the mmeory uses. 250 size_t sizeToPage = 0u; 251 // guest physical address. 252 uintptr_t gpa = 0u; 253 254 VK_EXT_MEMORY_HANDLE externalHandle = VK_EXT_MEMORY_HANDLE_INVALID; 255 256 bool dedicatedAllocation = false; 257 }; 258 259 // 128 mb staging buffer (really, just a few 4K frames or one 4k HDR frame) 260 // ought to be big enough for anybody! 261 static constexpr VkDeviceSize kDefaultStagingBufferSize = 128ULL * 1048576ULL; 262 263 struct StagingBufferInfo { 264 // TODO: Don't actually use this as external memory until host visible 265 // external is supported on all platforms 266 ExternalMemoryInfo memory; 267 VkBuffer buffer = VK_NULL_HANDLE; 268 VkDeviceSize size = kDefaultStagingBufferSize; 269 }; 270 271 enum class VulkanMode { 272 // Default: ColorBuffers can still be used with the existing GL-based 273 // API. Synchronization with (if it exists) Vulkan images happens on 274 // every one of the GL-based API calls: 275 // 276 // rcReadColorBuffer 277 // rcUpdateColorBuffer 278 // rcBindTexture 279 // rcBindRenderbuffer 280 // rcFlushWindowColorBuffer 281 // 282 // either through explicit CPU copies or implicit in the host driver 283 // if OpenGL interop is supported. 284 // 285 // When images are posted (rcFBPost), 286 // eglSwapBuffers is used, even if that requires a CPU readback. 287 288 Default = 0, 289 290 // VulkanOnly: It is assumed that the guest interacts entirely with 291 // the underlying Vulkan image in the guest and does not use the 292 // GL-based API. This means we can assume those APIs are not called: 293 // 294 // rcReadColorBuffer 295 // rcUpdateColorBuffer 296 // rcBindTexture 297 // rcBindRenderbuffer 298 // rcFlushWindowColorBuffer 299 // 300 // and thus we skip a lot of GL/Vk synchronization. 301 // 302 // When images are posted, eglSwapBuffers is only used if OpenGL 303 // interop is supported. If OpenGL interop is not supported, then we 304 // use a host platform-specific Vulkan swapchain to display the 305 // results. 306 307 VulkanOnly = 1, 308 }; 309 struct ColorBufferInfo { 310 ExternalMemoryInfo memory; 311 312 uint32_t handle; 313 314 /* Set in create(), before initialize() */ 315 uint32_t width; 316 uint32_t height; 317 GLenum internalFormat; 318 uint32_t memoryProperty; 319 int frameworkFormat; 320 int frameworkStride; 321 bool initialized = false; 322 323 VkImage image = VK_NULL_HANDLE; 324 VkImageView imageView = VK_NULL_HANDLE; 325 VkImageCreateInfo imageCreateInfoShallow = {}; 326 VkMemoryRequirements memReqs; 327 328 VkImageLayout currentLayout = VK_IMAGE_LAYOUT_UNDEFINED; 329 uint32_t currentQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL; 330 331 bool glExported = false; 332 bool externalMemoryCompatible = false; 333 334 VulkanMode vulkanMode = VulkanMode::Default; 335 336 MTLTextureRef mtlTexture = nullptr; 337 }; 338 339 struct BufferInfo { 340 ExternalMemoryInfo memory; 341 uint32_t handle; 342 343 VkDeviceSize size; 344 VkBufferCreateFlags createFlags; 345 VkBufferUsageFlags usageFlags; 346 VkSharingMode sharingMode; 347 348 VkBuffer buffer = VK_NULL_HANDLE; 349 VkMemoryRequirements memReqs; 350 351 bool glExported = false; 352 VulkanMode vulkanMode = VulkanMode::Default; 353 MTLBufferRef mtlBuffer = nullptr; 354 }; 355 356 // Track what is supported on whatever device was selected. 357 DeviceSupportInfo deviceInfo; 358 359 // Track additional vulkan diagnostics 360 uint32_t vulkanInstanceVersion; 361 std::vector<VkExtensionProperties> instanceExtensions; 362 363 // A single staging buffer to perform most transfers to/from OpenGL on the 364 // host. It is shareable across instances. The memory is shareable but the 365 // buffer is not; other users need to create buffers that 366 // bind to imported versions of the memory. 367 StagingBufferInfo staging; 368 369 // ColorBuffers are intended to back the guest's shareable images. 370 // For example: 371 // Android: gralloc 372 // Fuchsia: ImagePipeHandle 373 // Linux: dmabuf 374 std::unordered_map<uint32_t, ColorBufferInfo> colorBuffers; 375 376 // Buffers are intended to back the guest's shareable Vulkan buffers. 377 std::unordered_map<uint32_t, BufferInfo> buffers; 378 379 // In order to support VK_KHR_external_memory_(fd|win32) we need also to 380 // support the concept of plain external memories that are just memory and 381 // not necessarily images. These are then intended to pass through to the 382 // guest in some way, with 1:1 mapping between guest and host external 383 // memory handles. 384 std::unordered_map<uint32_t, ExternalMemoryInfo> externalMemories; 385 386 // The host keeps a set of occupied guest memory addresses to avoid a 387 // host memory address mapped to guest twice. 388 std::unordered_set<uint64_t> occupiedGpas; 389 390 // We can also consider using a single external memory object to back all 391 // host visible allocations in the guest. This would save memory, but we 392 // would also need to automatically add 393 // VkExternalMemory(Image|Buffer)CreateInfo, or if it is already there, OR 394 // it with the handle types on the host. 395 // A rough sketch: Some memories/images/buffers in the guest 396 // are backed by host visible memory: 397 // There is already a virtual memory type for those things in the current 398 // implementation. The guest doesn't know whether the pointer or the 399 // VkDeviceMemory object is backed by host external or non external. 400 // TODO: are all possible buffer / image usages compatible with 401 // external backing? 402 // TODO: try switching to this 403 ExternalMemoryInfo virtualHostVisibleHeap; 404 405 // Every command buffer in the pool is associated with a VkFence which is 406 // signaled only if the command buffer completes. 407 std::vector<std::tuple<VkCommandBuffer, VkFence>> transferQueueCommandBufferPool; 408 409 std::unique_ptr<CompositorVk> compositorVk; 410 411 // The implementation for Vulkan native swapchain. Only initialized in initVkEmulationFeatures 412 // if useVulkanNativeSwapchain is set. 413 std::unique_ptr<DisplayVk> displayVk; 414 415 struct RepresentativeColorBufferMemoryTypeInfo { 416 // The host memory type index used for Buffer/ColorBuffer allocations. 417 uint32_t hostMemoryTypeIndex; 418 419 // The guest memory type index that will be returned to guest processes querying 420 // the memory type index of host AHardwareBuffer/ColorBuffer allocations. This may 421 // point to an emulated memory type so that the host can control which memory flags are 422 // exposed to the guest (i.e. hide VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT from the guest). 423 uint32_t guestMemoryTypeIndex; 424 }; 425 std::optional<RepresentativeColorBufferMemoryTypeInfo> representativeColorBufferMemoryTypeInfo; 426 }; 427 428 VkEmulation* createGlobalVkEmulation(VulkanDispatch* vk, gfxstream::host::FeatureSet features); 429 430 struct VkEmulationFeatures { 431 bool glInteropSupported = false; 432 bool deferredCommands = false; 433 bool createResourceWithRequirements = false; 434 bool useVulkanComposition = false; 435 bool useVulkanNativeSwapchain = false; 436 std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> guestRenderDoc = nullptr; 437 AstcEmulationMode astcLdrEmulationMode = AstcEmulationMode::Disabled; 438 bool enableEtc2Emulation = false; 439 bool enableYcbcrEmulation = false; 440 bool guestUsesAngle = false; 441 bool useDedicatedAllocations = false; 442 }; 443 void initVkEmulationFeatures(std::unique_ptr<VkEmulationFeatures>); 444 445 VkEmulation* getGlobalVkEmulation(); 446 void teardownGlobalVkEmulation(); 447 448 std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window, 449 uint32_t width, uint32_t height); 450 451 bool allocExternalMemory( 452 VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info, bool actuallyExternal = true, 453 android::base::Optional<uint64_t> deviceAlignment = android::base::kNullopt, 454 android::base::Optional<VkBuffer> bufferForDedicatedAllocation = android::base::kNullopt, 455 android::base::Optional<VkImage> imageForDedicatedAllocation = android::base::kNullopt); 456 void freeExternalMemoryLocked(VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info); 457 458 bool importExternalMemory(VulkanDispatch* vk, VkDevice targetDevice, 459 const VkEmulation::ExternalMemoryInfo* info, VkDeviceMemory* out); 460 bool importExternalMemoryDedicatedImage(VulkanDispatch* vk, VkDevice targetDevice, 461 const VkEmulation::ExternalMemoryInfo* info, VkImage image, 462 VkDeviceMemory* out); 463 464 // ColorBuffer operations 465 466 bool getColorBufferShareInfo(uint32_t colorBufferHandle, bool* glExported, 467 bool* externalMemoryCompatible); 468 469 bool getColorBufferAllocationInfo(uint32_t colorBufferHandle, VkDeviceSize* outSize, 470 uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc, 471 void** outMappedPtr); 472 473 std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo(VkFormat format, 474 uint32_t width, 475 uint32_t height, 476 VkImageTiling tiling); 477 478 bool createVkColorBuffer(uint32_t width, uint32_t height, GLenum format, 479 FrameworkFormat frameworkFormat, uint32_t colorBufferHandle, 480 bool vulkanOnly, uint32_t memoryProperty); 481 482 bool teardownVkColorBuffer(uint32_t colorBufferHandle); 483 484 bool importExtMemoryHandleToVkColorBuffer(uint32_t colorBufferHandle, uint32_t type, 485 VK_EXT_MEMORY_HANDLE extMemHandle); 486 487 VkEmulation::ColorBufferInfo getColorBufferInfo(uint32_t colorBufferHandle); 488 VK_EXT_MEMORY_HANDLE getColorBufferExtMemoryHandle(uint32_t colorBufferHandle); 489 490 struct VkColorBufferMemoryExport { 491 android::base::ManagedDescriptor descriptor; 492 uint64_t size = 0; 493 bool linearTiling = false; 494 bool dedicatedAllocation = false; 495 }; 496 std::optional<VkColorBufferMemoryExport> exportColorBufferMemory(uint32_t colorBufferHandle); 497 498 MTLTextureRef getColorBufferMTLTexture(uint32_t colorBufferHandle); 499 bool setColorBufferVulkanMode(uint32_t colorBufferHandle, uint32_t vulkanMode); 500 int32_t mapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa, uint64_t size = 0); 501 502 bool colorBufferNeedsUpdateBetweenGlAndVk(uint32_t colorBufferHandle); 503 504 bool readColorBufferToBytes(uint32_t colorBufferHandle, std::vector<uint8_t>* bytes); 505 bool readColorBufferToBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w, 506 uint32_t h, void* outPixels); 507 bool readColorBufferToBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w, 508 uint32_t h, void* outPixels); 509 510 bool updateColorBufferFromBytes(uint32_t colorBufferHandle, const std::vector<uint8_t>& bytes); 511 bool updateColorBufferFromBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w, 512 uint32_t h, const void* pixels); 513 514 // Data buffer operations 515 bool getBufferAllocationInfo(uint32_t bufferHandle, VkDeviceSize* outSize, 516 uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc); 517 518 bool setupVkBuffer(uint64_t size, uint32_t bufferHandle, bool vulkanOnly = false, 519 uint32_t memoryProperty = 0); 520 bool teardownVkBuffer(uint32_t bufferHandle); 521 VK_EXT_MEMORY_HANDLE getBufferExtMemoryHandle(uint32_t bufferHandle); 522 523 bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes); 524 bool updateBufferFromBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, 525 const void* bytes); 526 527 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_tohost( 528 VkExternalMemoryHandleTypeFlags bits); 529 530 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_fromhost( 531 VkExternalMemoryHandleTypeFlags hostBits, 532 VkExternalMemoryHandleTypeFlags wantedGuestHandleType); 533 534 VkExternalMemoryProperties transformExternalMemoryProperties_tohost( 535 VkExternalMemoryProperties props); 536 537 VkExternalMemoryProperties transformExternalMemoryProperties_fromhost( 538 VkExternalMemoryProperties props, VkExternalMemoryHandleTypeFlags wantedGuestHandleType); 539 540 void setColorBufferCurrentLayout(uint32_t colorBufferHandle, VkImageLayout); 541 542 VkImageLayout getColorBufferCurrentLayout(uint32_t colorBufferHandle); 543 544 void releaseColorBufferForGuestUse(uint32_t colorBufferHandle); 545 546 std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForComposition(uint32_t colorBufferHandle, 547 bool colorBufferIsTarget); 548 std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForDisplay(uint32_t colorBufferHandle); 549 550 } // namespace vk 551 } // namespace gfxstream 552