blob: bb50ca36b958a22ad3ab18c202aa056da88bb05f [file] [log] [blame]
// Copyright 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <GLES2/gl2.h>
#include <vulkan/vulkan.h>
#include <atomic>
#include <functional>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "BorrowedImageVk.h"
#include "CompositorVk.h"
#include "DebugUtilsHelper.h"
#include "DeviceLostHelper.h"
#include "DisplayVk.h"
#include "ExternalObjectManager.h"
#include "FrameworkFormats.h"
#include "aemu/base/Optional.h"
#include "aemu/base/ThreadAnnotations.h"
#include "gfxstream/host/BackendCallbacks.h"
#include "gfxstream/host/Features.h"
#include "goldfish_vk_private_defs.h"
#include "utils/GfxApiLogger.h"
#include "utils/RenderDoc.h"
#if defined(_WIN32)
typedef void* HANDLE;
// External sync objects are HANDLE on Windows
typedef HANDLE VK_EXT_SYNC_HANDLE;
// corresponds to INVALID_HANDLE_VALUE
#define VK_EXT_SYNC_HANDLE_INVALID (VK_EXT_SYNC_HANDLE)(uintptr_t)(-1)
#else
// External sync objects are fd's on other POSIX systems
typedef int VK_EXT_SYNC_HANDLE;
#define VK_EXT_SYNC_HANDLE_INVALID (-1)
#endif
namespace gfxstream {
namespace vk {
struct VulkanDispatch;
// Returns a consistent answer for which memory type index is best for staging
// memory. This is not the simplest thing in the world because even if a memory
// type index is host visible, that doesn't mean a VkBuffer is allowed to be
// associated with it.
bool getStagingMemoryTypeIndex(VulkanDispatch* vk, VkDevice device,
const VkPhysicalDeviceMemoryProperties* memProps,
uint32_t* typeIndex);
enum class AstcEmulationMode {
Disabled, // No ASTC emulation (ie: ASTC not supported unless the GPU supports it natively)
Cpu, // Decompress ASTC textures on the CPU
Gpu, // Decompress ASTC textures on the GPU
};
// Global state that holds a global Vulkan instance along with globally
// exported memory allocations + images. This is in order to service things
// like AndroidHardwareBuffer/FuchsiaImagePipeHandle. Each such allocation is
// associated with a ColorBuffer handle, and depending on host-side support for
// GL_EXT_memory_object, also be able to zero-copy render into and readback
// with the traditional GL pipeline.
class VkEmulation {
public:
~VkEmulation();
static std::unique_ptr<VkEmulation> create(VulkanDispatch* vk,
gfxstream::host::BackendCallbacks callbacks,
gfxstream::host::FeatureSet features);
struct Features {
bool glInteropSupported = false;
bool deferredCommands = false;
bool createResourceWithRequirements = false;
bool useVulkanComposition = false;
bool useVulkanNativeSwapchain = false;
std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> guestRenderDoc = nullptr;
AstcEmulationMode astcLdrEmulationMode = AstcEmulationMode::Disabled;
bool enableEtc2Emulation = false;
bool enableYcbcrEmulation = false;
bool guestVulkanOnly = false;
bool useDedicatedAllocations = false;
};
void initFeatures(Features features);
bool isYcbcrEmulationEnabled() const;
bool isEtc2EmulationEnabled() const;
bool deferredCommandsEnabled() const;
bool createResourcesWithRequirementsEnabled() const;
bool supportsExternalMemoryCapabilities() const;
bool supportsExternalSemaphoreCapabilities() const;
bool supportsExternalFenceCapabilities() const;
bool supportsSurfaces() const;
bool supportsMoltenVk() const;
bool supportsGetPhysicalDeviceProperties2() const;
bool supportsPhysicalDeviceIDProperties() const;
std::optional<std::array<uint8_t, VK_UUID_SIZE>> getDeviceUuid();
std::optional<std::array<uint8_t, VK_UUID_SIZE>> getDriverUuid();
bool supportsPrivateData() const;
bool supportsExternalMemoryImport() const;
bool supportsDmaBuf() const;
bool supportsExternalMemoryHostProperties() const;
VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties() const;
bool isGuestVulkanOnly() const;
bool commandBufferCheckpointsEnabled() const;
bool supportsSamplerYcbcrConversion() const;
bool debugUtilsEnabled() const;
DebugUtilsHelper& getDebugUtilsHelper();
DeviceLostHelper& getDeviceLostHelper();
const gfxstream::host::FeatureSet& getFeatures() const;
const gfxstream::host::BackendCallbacks& getCallbacks() const;
AstcEmulationMode getAstcLdrEmulationMode() const;
emugl::RenderDocWithMultipleVkInstances* getRenderDoc();
Compositor* getCompositor();
DisplayVk* getDisplay();
VkInstance getInstance();
std::string getGpuVendor() const;
std::string getGpuName() const;
std::string getGpuVersionString() const;
std::string getInstanceExtensionsString() const;
std::string getDeviceExtensionsString() const;
const VkPhysicalDeviceProperties getPhysicalDeviceProperties() const;
struct RepresentativeColorBufferMemoryTypeInfo {
// The host memory type index used for Buffer/ColorBuffer allocations.
uint32_t hostMemoryTypeIndex;
// The guest memory type index that will be returned to guest processes querying
// the memory type index of host AHardwareBuffer/ColorBuffer allocations. This may
// point to an emulated memory type so that the host can control which memory flags are
// exposed to the guest (i.e. hide VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT from the guest).
uint32_t guestMemoryTypeIndex;
};
RepresentativeColorBufferMemoryTypeInfo getRepresentativeColorBufferMemoryTypeInfo() const;
void onVkDeviceLost();
VkExternalMemoryHandleTypeFlagBits getDefaultExternalMemoryHandleType();
std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window,
uint32_t width,
uint32_t height);
// ColorBuffer operations
bool getColorBufferShareInfo(uint32_t colorBufferHandle, bool* glExported,
bool* externalMemoryCompatible);
bool getColorBufferAllocationInfo(uint32_t colorBufferHandle, VkDeviceSize* outSize,
uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc,
void** outMappedPtr);
std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo(VkFormat format,
uint32_t width,
uint32_t height,
VkImageTiling tiling);
bool isFormatSupported(GLenum format);
bool createVkColorBuffer(uint32_t width, uint32_t height, GLenum format,
FrameworkFormat frameworkFormat, uint32_t colorBufferHandle,
bool vulkanOnly, uint32_t memoryProperty);
bool teardownVkColorBuffer(uint32_t colorBufferHandle);
struct ExternalMemoryInfo {
// Input fields
VkDeviceSize size;
uint32_t typeIndex;
// Output fields
uint32_t id = 0;
VkDeviceMemory memory = VK_NULL_HANDLE;
// host-mapping fields
// host virtual address (hva).
void* mappedPtr = nullptr;
// host virtual address, aligned to 4KB page.
void* pageAlignedHva = nullptr;
// the offset of |mappedPtr| off its memory page.
uint32_t pageOffset = 0u;
// the offset set in |vkBindImageMemory| or |vkBindBufferMemory|.
uint32_t bindOffset = 0u;
// the size of all the pages the memory uses.
size_t sizeToPage = 0u;
// guest physical address.
uintptr_t gpa = 0u;
std::optional<ExternalHandleInfo> handleInfo = std::nullopt;
#ifdef __APPLE__
// This is used as an external handle when MoltenVK is enabled
MTLResource_id externalMetalHandle = nullptr;
#endif
bool dedicatedAllocation = false;
};
bool allocExternalMemory(
VulkanDispatch* vk, ExternalMemoryInfo* info, bool actuallyExternal = true,
android::base::Optional<uint64_t> deviceAlignment = android::base::kNullopt,
android::base::Optional<VkBuffer> bufferForDedicatedAllocation = android::base::kNullopt,
android::base::Optional<VkImage> imageForDedicatedAllocation = android::base::kNullopt);
bool importExternalMemory(VulkanDispatch* vk, VkDevice targetDevice,
const ExternalMemoryInfo* info,
VkMemoryDedicatedAllocateInfo* dedicatedAllocInfo,
VkDeviceMemory* out);
enum class VulkanMode {
// Default: ColorBuffers can still be used with the existing GL-based
// API. Synchronization with (if it exists) Vulkan images happens on
// every one of the GL-based API calls:
//
// rcReadColorBuffer
// rcUpdateColorBuffer
// rcBindTexture
// rcBindRenderbuffer
// rcFlushWindowColorBuffer
//
// either through explicit CPU copies or implicit in the host driver
// if OpenGL interop is supported.
//
// When images are posted (rcFBPost),
// eglSwapBuffers is used, even if that requires a CPU readback.
Default = 0,
// VulkanOnly: It is assumed that the guest interacts entirely with
// the underlying Vulkan image in the guest and does not use the
// GL-based API. This means we can assume those APIs are not called:
//
// rcReadColorBuffer
// rcUpdateColorBuffer
// rcBindTexture
// rcBindRenderbuffer
// rcFlushWindowColorBuffer
//
// and thus we skip a lot of GL/Vk synchronization.
//
// When images are posted, eglSwapBuffers is only used if OpenGL
// interop is supported. If OpenGL interop is not supported, then we
// use a host platform-specific Vulkan swapchain to display the
// results.
VulkanOnly = 1,
};
struct ColorBufferInfo {
ExternalMemoryInfo memory;
uint32_t handle;
/* Set in create(), before initialize() */
uint32_t width;
uint32_t height;
GLenum internalFormat;
uint32_t memoryProperty;
int frameworkFormat;
int frameworkStride;
bool initialized = false;
VkImage image = VK_NULL_HANDLE;
VkImageView imageView = VK_NULL_HANDLE;
VkSamplerYcbcrConversion ycbcrConversion = VK_NULL_HANDLE;
VkImageCreateInfo imageCreateInfoShallow = {};
VkImageLayout currentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
uint32_t currentQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
bool glExported = false;
bool externalMemoryCompatible = false;
VulkanMode vulkanMode = VulkanMode::Default;
};
std::optional<VkEmulation::ColorBufferInfo> getColorBufferInfo(uint32_t colorBufferHandle);
struct BufferInfo {
ExternalMemoryInfo memory;
uint32_t handle;
VkDeviceSize size;
VkBufferCreateFlags createFlags;
VkBufferUsageFlags usageFlags;
VkSharingMode sharingMode;
VkBuffer buffer = VK_NULL_HANDLE;
bool glExported = false;
VulkanMode vulkanMode = VulkanMode::Default;
};
std::optional<ExternalHandleInfo> dupColorBufferExtMemoryHandle(uint32_t colorBufferHandle);
#ifdef __APPLE__
MTLResource_id getColorBufferMetalMemoryHandle(uint32_t colorBufferHandle);
VkImage getColorBufferVkImage(uint32_t colorBufferHandle);
#endif
struct VkColorBufferMemoryExport {
ExternalHandleInfo handleInfo;
uint64_t size = 0;
bool linearTiling = false;
bool dedicatedAllocation = false;
};
std::optional<VkColorBufferMemoryExport> exportColorBufferMemory(uint32_t colorBufferHandle);
bool setColorBufferVulkanMode(uint32_t colorBufferHandle, uint32_t vulkanMode);
int32_t mapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa, uint64_t size = 0);
bool colorBufferNeedsUpdateBetweenGlAndVk(uint32_t colorBufferHandle);
bool readColorBufferToBytes(uint32_t colorBufferHandle, std::vector<uint8_t>* bytes);
bool readColorBufferToBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
uint32_t h, void* outPixels, uint64_t outPixelsSize);
bool updateColorBufferFromBytes(uint32_t colorBufferHandle, const std::vector<uint8_t>& bytes);
bool updateColorBufferFromBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
uint32_t h, const void* pixels);
// Data buffer operations
bool getBufferAllocationInfo(uint32_t bufferHandle, VkDeviceSize* outSize,
uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc);
bool setupVkBuffer(uint64_t size, uint32_t bufferHandle, bool vulkanOnly = false,
uint32_t memoryProperty = 0);
bool teardownVkBuffer(uint32_t bufferHandle);
std::optional<GenericDescriptorInfo> exportMemoryHandle(VkDevice device, VkDeviceMemory memory);
std::optional<ExternalHandleInfo> dupBufferExtMemoryHandle(uint32_t bufferHandle);
#ifdef __APPLE__
MTLResource_id getBufferMetalMemoryHandle(uint32_t bufferHandle);
MTLResource_id getMtlResourceFromVkDeviceMemory(VulkanDispatch* vk, VkDeviceMemory memory);
#endif
bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes);
bool updateBufferFromBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size,
const void* bytes);
VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_tohost(
VkExternalMemoryHandleTypeFlags bits);
VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_fromhost(
VkExternalMemoryHandleTypeFlags hostBits,
VkExternalMemoryHandleTypeFlags wantedGuestHandleType);
VkExternalMemoryProperties transformExternalMemoryProperties_tohost(
VkExternalMemoryProperties props);
VkExternalMemoryProperties transformExternalMemoryProperties_fromhost(
VkExternalMemoryProperties props, VkExternalMemoryHandleTypeFlags wantedGuestHandleType);
void setColorBufferCurrentLayout(uint32_t colorBufferHandle, VkImageLayout);
VkImageLayout getColorBufferCurrentLayout(uint32_t colorBufferHandle);
void releaseColorBufferForGuestUse(uint32_t colorBufferHandle);
std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForComposition(uint32_t colorBufferHandle,
bool colorBufferIsTarget);
std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForDisplay(uint32_t colorBufferHandle);
private:
VkEmulation() = default;
std::optional<RepresentativeColorBufferMemoryTypeInfo>
findRepresentativeColorBufferMemoryTypeIndexLocked() REQUIRES(mMutex);
struct ImageSupportInfo {
// Input parameters
VkFormat format;
VkImageType type;
VkImageTiling tiling;
VkImageUsageFlags usageFlags;
VkImageCreateFlags createFlags;
// Output parameters
bool supported = false;
bool supportsExternalMemory = false;
bool requiresDedicatedAllocation = false;
// Keep the raw output around.
VkFormatProperties2 formatProps2;
VkImageFormatProperties2 imageFormatProps2;
VkExternalImageFormatProperties extFormatProps;
};
static std::vector<VkEmulation::ImageSupportInfo> getBasicImageSupportList();
// For a given ImageSupportInfo, populates usageWithExternalHandles and
// requiresDedicatedAllocation. memoryTypeBits are populated later once the
// device is created, because that needs a test image to be created.
// If we don't support external memory, it's assumed dedicated allocations are
// not needed.
// Precondition: sVkEmulation instance has been created and ext memory caps known.
// Returns false if the query failed.
bool populateImageFormatExternalMemorySupportInfo(VulkanDispatch* vk, VkPhysicalDevice physdev,
ImageSupportInfo* info);
struct DeviceSupportInfo {
bool hasGraphicsQueueFamily = false;
bool hasComputeQueueFamily = false;
bool supportsExternalMemoryImport = false;
bool supportsExternalMemoryExport = false;
bool supportsDmaBuf = false;
bool supportsDriverProperties = false;
bool supportsExternalMemoryHostProps = false;
bool hasSamplerYcbcrConversionExtension = false;
bool supportsSamplerYcbcrConversion = false;
bool glInteropSupported = false;
bool hasNvidiaDeviceDiagnosticCheckpointsExtension = false;
bool supportsNvidiaDeviceDiagnosticCheckpoints = false;
bool supportsPrivateData = false;
std::vector<VkExtensionProperties> extensions;
std::vector<uint32_t> graphicsQueueFamilyIndices;
std::vector<uint32_t> computeQueueFamilyIndices;
VkPhysicalDeviceProperties physdevProps;
VkPhysicalDeviceMemoryProperties memProps;
VkPhysicalDeviceIDPropertiesKHR idProps;
VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProps;
std::string driverVendor;
std::string driverVersion;
PFN_vkGetImageMemoryRequirements2KHR getImageMemoryRequirements2Func = nullptr;
PFN_vkGetBufferMemoryRequirements2KHR getBufferMemoryRequirements2Func = nullptr;
#ifdef _WIN32
PFN_vkGetMemoryWin32HandleKHR getMemoryHandleFunc = nullptr;
#else
PFN_vkGetMemoryFdKHR getMemoryHandleFunc = nullptr;
#endif
};
uint32_t getValidMemoryTypeIndex(uint32_t requiredMemoryTypeBits,
VkMemoryPropertyFlags memoryProperty = 0);
int getSelectedGpuIndex(const std::vector<DeviceSupportInfo>& deviceInfos);
bool isFormatVulkanCompatible(GLenum internalFormat);
bool getColorBufferAllocationInfoLocked(uint32_t colorBufferHandle, VkDeviceSize* outSize,
uint32_t* outMemoryTypeIndex,
bool* outMemoryIsDedicatedAlloc, void** outMappedPtr) REQUIRES(mMutex);
std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfoLocked(
VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling) REQUIRES(mMutex);
bool createVkColorBufferLocked(uint32_t width, uint32_t height, GLenum internalFormat,
FrameworkFormat frameworkFormat, uint32_t colorBufferHandle,
bool vulkanOnly, uint32_t memoryProperty) REQUIRES(mMutex);
bool teardownVkColorBufferLocked(uint32_t colorBufferHandle) REQUIRES(mMutex);
bool colorBufferNeedsUpdateBetweenGlAndVk(const VkEmulation::ColorBufferInfo& colorBufferInfo);
bool readColorBufferToBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, void* outPixels,
uint64_t outPixelsSize) REQUIRES(mMutex);
bool updateColorBufferFromBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, const void* pixels,
size_t inputPixelsSize) REQUIRES(mMutex);
bool updateMemReqsForExtMem(std::optional<ExternalHandleInfo> extMemHandleInfo,
VkMemoryRequirements* pMemReqs);
std::tuple<VkCommandBuffer, VkFence> allocateQueueTransferCommandBufferLocked() REQUIRES(mMutex);
void freeExternalMemoryLocked(VulkanDispatch* vk, ExternalMemoryInfo* info) REQUIRES(mMutex);
std::mutex mMutex;
gfxstream::host::BackendCallbacks mCallbacks;
gfxstream::host::FeatureSet mFeatures;
RepresentativeColorBufferMemoryTypeInfo mRepresentativeColorBufferMemoryTypeInfo;
// Whether to use deferred command submission.
bool mUseDeferredCommands = false;
// Whether to fuse memory requirements getting with resource creation.
bool mUseCreateResourcesWithRequirements = false;
// RenderDoc integration for guest VkInstances.
std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> mGuestRenderDoc;
// Whether to use ASTC emulation. Our current ASTC decoder implementation may lead to device
// lost on certain device on Windows.
AstcEmulationMode mAstcLdrEmulationMode = AstcEmulationMode::Disabled;
// Whether to use ETC2 emulation.
bool mEnableEtc2Emulation = false;
// Whether to use Ycbcr emulation. If this feature is turned on, Ycbcr request will always use
// the emulation path regardless of whether the host Vulkan driver actually supports Ycbcr
// conversion or not.
bool mEnableYcbcrEmulation = false;
bool mGuestVulkanOnly = false;
bool mUseDedicatedAllocations = false;
// Instance and device for creating the system-wide shareable objects.
VkInstance mInstance = VK_NULL_HANDLE;
uint32_t mVulkanInstanceVersion = 0;
std::vector<VkExtensionProperties> mInstanceExtensions;
uint32_t mPhysicalDeviceIndex = 0;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
VkDevice mDevice = VK_NULL_HANDLE;
// Global, instance and device dispatch tables.
VulkanDispatch* mGvk = nullptr;
VulkanDispatch* mIvk = nullptr;
VulkanDispatch* mDvk = nullptr;
bool mInstanceSupportsPhysicalDeviceIDProperties = false;
bool mInstanceSupportsGetPhysicalDeviceProperties2 = false;
bool mInstanceSupportsExternalMemoryCapabilities = false;
bool mInstanceSupportsExternalSemaphoreCapabilities = false;
bool mInstanceSupportsExternalFenceCapabilities = false;
bool mInstanceSupportsSurface = false;
#if defined(__APPLE__)
bool mInstanceSupportsMoltenVK = false;
#else
static const bool mInstanceSupportsMoltenVK = false;
#endif
PFN_vkGetPhysicalDeviceImageFormatProperties2KHR mGetImageFormatProperties2Func = nullptr;
PFN_vkGetPhysicalDeviceProperties2KHR mGetPhysicalDeviceProperties2Func = nullptr;
PFN_vkGetPhysicalDeviceFeatures2 mGetPhysicalDeviceFeatures2Func = nullptr;
bool mDebugUtilsAvailableAndRequested = false;
DebugUtilsHelper mDebugUtilsHelper = DebugUtilsHelper::withUtilsDisabled();
bool mCommandBufferCheckpointsSupportedAndRequested = false;
DeviceLostHelper mDeviceLostHelper{};
// Queue, command pool, and command buffer
// for running commands to sync stuff system-wide.
// TODO(b/197362803): Encapsulate host side VkQueue and the lock.
VkQueue mQueue = VK_NULL_HANDLE;
std::shared_ptr<android::base::Lock> mQueueLock = nullptr;
uint32_t mQueueFamilyIndex = 0;
VkCommandPool mCommandPool = VK_NULL_HANDLE;
VkCommandBuffer mCommandBuffer = VK_NULL_HANDLE;
VkFence mCommandBufferFence = VK_NULL_HANDLE;
std::vector<ImageSupportInfo> mImageSupportInfo;
// 128 mb staging buffer (really, just a few 4K frames or one 4k HDR frame)
// ought to be big enough for anybody!
static constexpr VkDeviceSize kDefaultStagingBufferSize = 128ULL * 1048576ULL;
struct StagingBufferInfo {
// TODO: Don't actually use this as external memory until host visible
// external is supported on all platforms
ExternalMemoryInfo memory;
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceSize size = kDefaultStagingBufferSize;
};
// Track what is supported on whatever device was selected.
DeviceSupportInfo mDeviceInfo;
// A single staging buffer to perform most transfers to/from OpenGL on the
// host. It is shareable across instances. The memory is shareable but the
// buffer is not; other users need to create buffers that
// bind to imported versions of the memory.
StagingBufferInfo mStaging GUARDED_BY(mMutex);
// ColorBuffers are intended to back the guest's shareable images.
// For example:
// Android: gralloc
// Fuchsia: ImagePipeHandle
// Linux: dmabuf
std::unordered_map<uint32_t, ColorBufferInfo> mColorBuffers GUARDED_BY(mMutex);
// Buffers are intended to back the guest's shareable Vulkan buffers.
std::unordered_map<uint32_t, BufferInfo> mBuffers GUARDED_BY(mMutex);
// In order to support VK_KHR_external_memory_(fd|win32) we need also to
// support the concept of plain external memories that are just memory and
// not necessarily images. These are then intended to pass through to the
// guest in some way, with 1:1 mapping between guest and host external
// memory handles.
std::unordered_map<uint32_t, ExternalMemoryInfo> mExternalMemories GUARDED_BY(mMutex);
// The host keeps a set of occupied guest memory addresses to avoid a
// host memory address mapped to guest twice.
std::unordered_set<uint64_t> mOccupiedGpas GUARDED_BY(mMutex);
// We can also consider using a single external memory object to back all
// host visible allocations in the guest. This would save memory, but we
// would also need to automatically add
// VkExternalMemory(Image|Buffer)CreateInfo, or if it is already there, OR
// it with the handle types on the host.
// A rough sketch: Some memories/images/buffers in the guest
// are backed by host visible memory:
// There is already a virtual memory type for those things in the current
// implementation. The guest doesn't know whether the pointer or the
// VkDeviceMemory object is backed by host external or non external.
// TODO: are all possible buffer / image usages compatible with
// external backing?
// TODO: try switching to this
ExternalMemoryInfo mVirtualHostVisibleHeap;
// Every command buffer in the pool is associated with a VkFence which is
// signaled only if the command buffer completes.
std::vector<std::tuple<VkCommandBuffer, VkFence>> mTransferQueueCommandBufferPool GUARDED_BY(mMutex);
std::unique_ptr<CompositorVk> mCompositorVk;
// The implementation for Vulkan native swapchain. Only initialized in initVkEmulationFeatures
// if useVulkanNativeSwapchain is set.
std::unique_ptr<DisplayVk> mDisplayVk;
};
} // namespace vk
} // namespace gfxstream