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