1 #ifndef DISPLAY_VK_H 2 #define DISPLAY_VK_H 3 4 #include <deque> 5 #include <functional> 6 #include <future> 7 #include <memory> 8 #include <optional> 9 #include <tuple> 10 #include <unordered_map> 11 #include <unordered_set> 12 13 #include "CompositorVk.h" 14 #include "Hwc2.h" 15 #include "RenderContext.h" 16 #include "SwapChainStateVk.h" 17 #include "base/Lock.h" 18 #include "vulkan/cereal/common/goldfish_vk_dispatch.h" 19 20 // The DisplayVk class holds the Vulkan and other states required to draw a 21 // frame in a host window. 22 23 class DisplayVk { 24 public: 25 class DisplayBufferInfo { 26 public: 27 ~DisplayBufferInfo(); 28 29 private: 30 DisplayBufferInfo(const goldfish_vk::VulkanDispatch &, VkDevice, const VkImageCreateInfo &, 31 VkImage); 32 33 const goldfish_vk::VulkanDispatch &m_vk; 34 VkDevice m_vkDevice; 35 VkImageCreateInfo m_vkImageCreateInfo; 36 37 VkImage m_vkImage; 38 VkImageView m_vkImageView; 39 // m_compositorVkRenderTarget will be created when the first time the ColorBuffer is used as 40 // the render target of DisplayVk::compose. DisplayVk owns the m_compositorVkRenderTarget so 41 // that when the CompositorVk is recreated m_compositorVkRenderTarget can be restored to 42 // nullptr. 43 std::weak_ptr<CompositorVkRenderTarget> m_compositorVkRenderTarget; 44 45 friend class DisplayVk; 46 }; 47 DisplayVk(const goldfish_vk::VulkanDispatch &, VkPhysicalDevice, 48 uint32_t swapChainQueueFamilyIndex, uint32_t compositorQueueFamilyIndex, VkDevice, 49 VkQueue compositorVkQueue, std::shared_ptr<android::base::Lock> compositorVkQueueLock, 50 VkQueue swapChainVkQueue, std::shared_ptr<android::base::Lock> swapChainVkQueueLock); 51 ~DisplayVk(); 52 void bindToSurface(VkSurfaceKHR, uint32_t width, uint32_t height); 53 // The caller is responsible to make sure the VkImage lives longer than the DisplayBufferInfo 54 // created here. 55 std::shared_ptr<DisplayBufferInfo> createDisplayBuffer(VkImage, const VkImageCreateInfo &); 56 // The first component of the returned tuple is false when the swapchain is no longer valid and 57 // bindToSurface() needs to be called again. When the first component is true, the second 58 // component of the returned tuple is a/ future that will complete when the GPU side of work 59 // completes. The caller is responsible to guarantee the synchronization and the layout of 60 // DisplayBufferInfo::m_vkImage is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL. 61 std::tuple<bool, std::shared_future<void>> post(std::shared_ptr<DisplayBufferInfo>); 62 63 // dstWidth and dstHeight describe the size of the render target the guest 64 // "thinks" it composes to, essentially, the virtual display size. Note that 65 // this can be different from the actual window size. The first component of 66 // the returned tuple is false when the swapchain is no longer valid and 67 // bindToSurface() needs to be called again. When the first component is 68 // true, the second component of the returned tuple is a future that will 69 // complete when the GPU side of work completes. 70 std::tuple<bool, std::shared_future<void>> compose( 71 uint32_t numLayers, const ComposeLayer layers[], 72 std::vector<std::shared_ptr<DisplayBufferInfo>> composeBuffers, 73 std::shared_ptr<DisplayBufferInfo> renderTarget); 74 75 private: 76 VkFormatFeatureFlags getFormatFeatures(VkFormat, VkImageTiling); 77 bool canPost(const VkImageCreateInfo &); 78 // Check if the VkImage can be used as the compose layer to be sampled from. 79 bool canCompositeFrom(const VkImageCreateInfo &); 80 // Check if the VkImage can be used as the render target of the composition. 81 bool canCompositeTo(const VkImageCreateInfo &); 82 // Returns if the composition specified by the parameter is different from 83 // the previous composition. If the composition is different, update the 84 // previous composition stored in m_surfaceState. Must be called after 85 // bindToSurface() is called. 86 bool compareAndSaveComposition( 87 uint32_t renderTargetIndex, uint32_t numLayers, const ComposeLayer layers[], 88 const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers); 89 90 const goldfish_vk::VulkanDispatch &m_vk; 91 VkPhysicalDevice m_vkPhysicalDevice; 92 uint32_t m_swapChainQueueFamilyIndex; 93 uint32_t m_compositorQueueFamilyIndex; 94 VkDevice m_vkDevice; 95 VkQueue m_compositorVkQueue; 96 std::shared_ptr<android::base::Lock> m_compositorVkQueueLock; 97 VkQueue m_swapChainVkQueue; 98 std::shared_ptr<android::base::Lock> m_swapChainVkQueueLock; 99 VkCommandPool m_vkCommandPool; 100 VkSampler m_compositionVkSampler; 101 102 class PostResource { 103 public: 104 const VkFence m_swapchainImageReleaseFence; 105 const VkSemaphore m_swapchainImageAcquireSemaphore; 106 const VkSemaphore m_swapchainImageReleaseSemaphore; 107 const VkCommandBuffer m_vkCommandBuffer; 108 static std::shared_ptr<PostResource> create(const goldfish_vk::VulkanDispatch &, VkDevice, 109 VkCommandPool); 110 ~PostResource(); 111 DISALLOW_COPY_ASSIGN_AND_MOVE(PostResource); 112 113 private: 114 PostResource(const goldfish_vk::VulkanDispatch &, VkDevice, VkCommandPool, 115 VkFence swapchainImageReleaseFence, VkSemaphore swapchainImageAcquireSemaphore, 116 VkSemaphore swapchainImageReleaseSemaphore, VkCommandBuffer); 117 const goldfish_vk::VulkanDispatch &m_vk; 118 const VkDevice m_vkDevice; 119 const VkCommandPool m_vkCommandPool; 120 }; 121 122 std::deque<std::shared_ptr<PostResource>> m_freePostResources; 123 std::optional<std::shared_future<std::shared_ptr<PostResource>>> m_postResourceFuture; 124 125 class ComposeResource { 126 public: 127 const VkFence m_composeCompleteFence; 128 const VkCommandBuffer m_vkCommandBuffer; 129 static std::unique_ptr<ComposeResource> create(const goldfish_vk::VulkanDispatch &, 130 VkDevice, VkCommandPool); 131 ~ComposeResource(); 132 DISALLOW_COPY_ASSIGN_AND_MOVE(ComposeResource); 133 134 private: 135 ComposeResource(const goldfish_vk::VulkanDispatch &, VkDevice, VkCommandPool, VkFence, 136 VkCommandBuffer); 137 const goldfish_vk::VulkanDispatch &m_vk; 138 const VkDevice m_vkDevice; 139 const VkCommandPool m_vkCommandPool; 140 }; 141 142 int m_inFlightFrameIndex; 143 std::optional<std::future<std::unique_ptr<ComposeResource>>> m_composeResourceFuture; 144 145 std::unique_ptr<SwapChainStateVk> m_swapChainStateVk; 146 std::unique_ptr<CompositorVk> m_compositorVk; 147 static constexpr uint32_t k_compositorVkRenderTargetCacheSize = 128; 148 std::deque<std::shared_ptr<CompositorVkRenderTarget>> m_compositorVkRenderTargets; 149 static constexpr VkFormat k_compositorVkRenderTargetFormat = VK_FORMAT_R8G8B8A8_UNORM; 150 struct SurfaceState { 151 struct Layer { 152 ComposeLayer m_hwc2Layer; 153 std::weak_ptr<DisplayBufferInfo> m_displayBuffer; 154 }; 155 156 uint32_t m_width = 0; 157 uint32_t m_height = 0; 158 std::unordered_map<uint32_t, std::vector<std::unique_ptr<Layer>>> m_prevCompositions; 159 }; 160 std::unique_ptr<SurfaceState> m_surfaceState; 161 162 std::unordered_map<VkFormat, VkFormatProperties> m_vkFormatProperties; 163 }; 164 165 #endif 166