• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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