1 #ifndef COMPOSITOR_VK_H 2 #define COMPOSITOR_VK_H 3 4 #include <array> 5 #include <deque> 6 #include <future> 7 #include <glm/glm.hpp> 8 #include <list> 9 #include <memory> 10 #include <optional> 11 #include <tuple> 12 #include <unordered_map> 13 #include <vector> 14 15 #include "BorrowedImage.h" 16 #include "BorrowedImageVk.h" 17 #include "Compositor.h" 18 #include "Hwc2.h" 19 #include "aemu/base/synchronization/Lock.h" 20 #include "aemu/base/LruCache.h" 21 #include "vulkan/cereal/common/goldfish_vk_dispatch.h" 22 #include "vulkan/vk_util.h" 23 24 namespace gfxstream { 25 namespace vk { 26 27 // We do see a composition requests with 12 layers. (b/222700096) 28 // Inside hwc2, we will ask for surfaceflinger to 29 // do the composition, if the layers more than 16. 30 // If we see rendering error or significant time spent on updating 31 // descriptors in setComposition, we should tune this number. 32 static constexpr const uint32_t kMaxLayersPerFrame = 16; 33 static const uint64_t kVkWaitForFencesTimeoutNsecs = 5ULL * 1000ULL * 1000ULL * 1000ULL; 34 35 // Base used to grant visibility to members to the vk_util::* helper classes. 36 struct CompositorVkBase : public vk_util::MultiCrtp<CompositorVkBase, // 37 vk_util::FindMemoryType, // 38 vk_util::RunSingleTimeCommand> { 39 const VulkanDispatch& m_vk; 40 const VkDevice m_vkDevice; 41 const VkPhysicalDevice m_vkPhysicalDevice; 42 const VkQueue m_vkQueue; 43 const uint32_t m_queueFamilyIndex; 44 std::shared_ptr<android::base::Lock> m_vkQueueLock; 45 VkDescriptorSetLayout m_vkDescriptorSetLayout; 46 VkPipelineLayout m_vkPipelineLayout; 47 VkRenderPass m_vkRenderPass; 48 VkPipeline m_graphicsVkPipeline; 49 VkBuffer m_vertexVkBuffer; 50 VkDeviceMemory m_vertexVkDeviceMemory; 51 VkBuffer m_indexVkBuffer; 52 VkDeviceMemory m_indexVkDeviceMemory; 53 VkDescriptorPool m_vkDescriptorPool; 54 VkCommandPool m_vkCommandPool; 55 // TODO: create additional VkSampler-s for YCbCr layers. 56 VkSampler m_vkSampler; 57 58 // The underlying storage for all of the uniform buffer objects. 59 struct UniformBufferStorage { 60 VkBuffer m_vkBuffer = VK_NULL_HANDLE; 61 VkDeviceMemory m_vkDeviceMemory = VK_NULL_HANDLE; 62 VkDeviceSize m_stride = 0; 63 } m_uniformStorage; 64 65 // Keep in sync with vulkan/Compositor.frag. 66 struct SamplerBinding { 67 VkImageView sampledImageView = VK_NULL_HANDLE; 68 }; 69 70 // Keep in sync with vulkan/Compositor.vert. 71 struct UniformBufferBinding { 72 alignas(16) glm::mat4 positionTransform; 73 alignas(16) glm::mat4 texCoordTransform; 74 }; 75 76 // The cached contents of a given descriptor set. 77 struct DescriptorSetContents { 78 SamplerBinding binding0; 79 UniformBufferBinding binding1; 80 }; 81 82 // The cached contents of all descriptors sets of a given frame. 83 struct FrameDescriptorSetsContents { 84 std::vector<DescriptorSetContents> descriptorSets; 85 }; 86 87 friend bool operator==(const DescriptorSetContents& lhs, const DescriptorSetContents& rhs); 88 89 friend bool operator==(const FrameDescriptorSetsContents& lhs, 90 const FrameDescriptorSetsContents& rhs); 91 92 struct PerFrameResources { 93 VkFence m_vkFence = VK_NULL_HANDLE; 94 VkCommandBuffer m_vkCommandBuffer = VK_NULL_HANDLE; 95 std::vector<VkDescriptorSet> m_layerDescriptorSets; 96 // Pointers into the underlying uniform buffer storage for the uniform 97 // buffer of part of each descriptor set for each layer. 98 std::vector<UniformBufferBinding*> m_layerUboStorages; 99 std::optional<FrameDescriptorSetsContents> m_vkDescriptorSetsContents; 100 }; 101 std::vector<PerFrameResources> m_frameResources; 102 std::deque<std::shared_future<PerFrameResources*>> m_availableFrameResources; 103 CompositorVkBaseCompositorVkBase104 explicit CompositorVkBase(const VulkanDispatch& vk, VkDevice device, 105 VkPhysicalDevice physicalDevice, VkQueue queue, 106 std::shared_ptr<android::base::Lock> queueLock, 107 uint32_t queueFamilyIndex, uint32_t maxFramesInFlight) 108 : m_vk(vk), 109 m_vkDevice(device), 110 m_vkPhysicalDevice(physicalDevice), 111 m_vkQueue(queue), 112 m_queueFamilyIndex(queueFamilyIndex), 113 m_vkQueueLock(queueLock), 114 m_vkDescriptorSetLayout(VK_NULL_HANDLE), 115 m_vkPipelineLayout(VK_NULL_HANDLE), 116 m_vkRenderPass(VK_NULL_HANDLE), 117 m_graphicsVkPipeline(VK_NULL_HANDLE), 118 m_vertexVkBuffer(VK_NULL_HANDLE), 119 m_vertexVkDeviceMemory(VK_NULL_HANDLE), 120 m_indexVkBuffer(VK_NULL_HANDLE), 121 m_indexVkDeviceMemory(VK_NULL_HANDLE), 122 m_vkDescriptorPool(VK_NULL_HANDLE), 123 m_vkCommandPool(VK_NULL_HANDLE), 124 m_vkSampler(VK_NULL_HANDLE), 125 m_frameResources(maxFramesInFlight) {} 126 }; 127 128 class CompositorVk : protected CompositorVkBase, public Compositor { 129 public: 130 static std::unique_ptr<CompositorVk> create(const VulkanDispatch& vk, VkDevice vkDevice, 131 VkPhysicalDevice vkPhysicalDevice, VkQueue vkQueue, 132 std::shared_ptr<android::base::Lock> queueLock, 133 uint32_t queueFamilyIndex, 134 uint32_t maxFramesInFlight); 135 136 ~CompositorVk(); 137 138 CompositionFinishedWaitable compose(const CompositionRequest& compositionRequest) override; 139 140 void onImageDestroyed(uint32_t imageId) override; 141 queueSupportsComposition(const VkQueueFamilyProperties & properties)142 static bool queueSupportsComposition(const VkQueueFamilyProperties& properties) { 143 return properties.queueFlags & VK_QUEUE_GRAPHICS_BIT; 144 } 145 146 private: 147 explicit CompositorVk(const VulkanDispatch&, VkDevice, VkPhysicalDevice, VkQueue, 148 std::shared_ptr<android::base::Lock> queueLock, uint32_t queueFamilyIndex, 149 uint32_t maxFramesInFlight); 150 151 void setUpGraphicsPipeline(); 152 void setUpVertexBuffers(); 153 void setUpSampler(); 154 void setUpDescriptorSets(); 155 void setUpUniformBuffers(); 156 void setUpCommandPool(); 157 void setUpFences(); 158 void setUpFrameResourceFutures(); 159 160 std::optional<std::tuple<VkBuffer, VkDeviceMemory>> createBuffer(VkDeviceSize, 161 VkBufferUsageFlags, 162 VkMemoryPropertyFlags) const; 163 std::tuple<VkBuffer, VkDeviceMemory> createStagingBufferWithData(const void* data, 164 VkDeviceSize size) const; 165 void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize) const; 166 167 VkFormatFeatureFlags getFormatFeatures(VkFormat format, VkImageTiling tiling); 168 169 // Check if the ColorBuffer can be used as a compose layer to be sampled from. 170 bool canCompositeFrom(const VkImageCreateInfo& info); 171 172 // Check if the ColorBuffer can be used as a render target of a composition. 173 bool canCompositeTo(const VkImageCreateInfo& info); 174 175 // A consolidated view of a `Compositor::CompositionRequestLayer` with only 176 // the Vulkan components needed for command recording and submission. 177 struct CompositionLayerVk { 178 VkImage image = VK_NULL_HANDLE; 179 VkImageView imageView = VK_NULL_HANDLE; 180 VkImageLayout preCompositionLayout = VK_IMAGE_LAYOUT_UNDEFINED; 181 uint32_t preCompositionQueueFamilyIndex = 0; 182 VkImageLayout postCompositionLayout = VK_IMAGE_LAYOUT_UNDEFINED; 183 uint32_t postCompositionQueueFamilyIndex = 0; 184 }; 185 186 // A consolidated view of a `Compositor::CompositionRequest` with only 187 // the Vulkan components needed for command recording and submission. 188 struct CompositionVk { 189 const BorrowedImageInfoVk* targetImage = nullptr; 190 VkFramebuffer targetFramebuffer = VK_NULL_HANDLE; 191 std::vector<const BorrowedImageInfoVk*> layersSourceImages; 192 FrameDescriptorSetsContents layersDescriptorSets; 193 }; 194 void buildCompositionVk(const CompositionRequest& compositionRequest, 195 CompositionVk* compositionVk); 196 197 void updateDescriptorSetsIfChanged(const FrameDescriptorSetsContents& contents, 198 PerFrameResources* frameResources); 199 200 class RenderTarget { 201 public: 202 ~RenderTarget(); 203 204 DISALLOW_COPY_ASSIGN_AND_MOVE(RenderTarget); 205 206 private: 207 friend class CompositorVk; 208 RenderTarget(const VulkanDispatch& vk, VkDevice vkDevice, VkImage vkImage, 209 VkImageView vkImageView, uint32_t width, uint32_t height, 210 VkRenderPass vkRenderPass); 211 212 const VulkanDispatch& m_vk; 213 VkDevice m_vkDevice; 214 VkImage m_vkImage; 215 VkFramebuffer m_vkFramebuffer; 216 uint32_t m_width; 217 uint32_t m_height; 218 }; 219 220 // Gets the RenderTarget used for composing into the given image if it already exists, 221 // otherwise creates it. 222 RenderTarget* getOrCreateRenderTargetInfo(const BorrowedImageInfoVk& info); 223 224 // Cached format properties used for checking if composition is supported with a given 225 // format. 226 std::unordered_map<VkFormat, VkFormatProperties> m_vkFormatProperties; 227 228 uint32_t m_maxFramesInFlight = 0; 229 230 static constexpr const VkFormat k_renderTargetFormat = VK_FORMAT_R8G8B8A8_UNORM; 231 static constexpr const uint32_t k_renderTargetCacheSize = 128; 232 // Maps from borrowed image ids to render target info. 233 android::base::LruCache<uint32_t, std::unique_ptr<RenderTarget>> m_renderTargetCache; 234 }; 235 236 } // namespace vk 237 } // namespace gfxstream 238 239 #endif /* COMPOSITOR_VK_H */ 240