#ifndef COMPOSITOR_VK_H #define COMPOSITOR_VK_H #include #include #include #include #include #include #include #include "Hwc2.h" #include "base/Lock.h" #include "vulkan/cereal/common/goldfish_vk_dispatch.h" #include "vulkan/vk_util.h" class ComposeLayerVk { public: VkSampler m_vkSampler; VkImageView m_vkImageView; struct LayerTransform { glm::mat4 pos; glm::mat4 texcoord; } m_layerTransform; static std::unique_ptr createFromHwc2ComposeLayer( VkSampler, VkImageView, const ComposeLayer &, uint32_t cbWidth, uint32_t cbHeight, uint32_t dstWidth, uint32_t dstHeight); private: ComposeLayerVk() = delete; explicit ComposeLayerVk(VkSampler, VkImageView, const LayerTransform &); }; // If we want to apply transform to all layers to rotate/clip/position the // virtual display, we should add that functionality here. class Composition { public: std::vector> m_composeLayers; Composition() = delete; explicit Composition(std::vector> composeLayers); }; class CompositorVkRenderTarget; struct CompositorVkBase : public vk_util::RunSingleTimeCommand< CompositorVkBase, vk_util::FindMemoryType>> { const goldfish_vk::VulkanDispatch &m_vk; const VkDevice m_vkDevice; const VkPhysicalDevice m_vkPhysicalDevice; const VkQueue m_vkQueue; std::shared_ptr m_vkQueueLock; VkDescriptorSetLayout m_vkDescriptorSetLayout; VkPipelineLayout m_vkPipelineLayout; VkRenderPass m_vkRenderPass; VkPipeline m_graphicsVkPipeline; VkBuffer m_vertexVkBuffer; VkDeviceMemory m_vertexVkDeviceMemory; VkBuffer m_indexVkBuffer; VkDeviceMemory m_indexVkDeviceMemory; VkDescriptorPool m_vkDescriptorPool; std::vector m_vkDescriptorSets; VkCommandPool m_vkCommandPool; explicit CompositorVkBase(const goldfish_vk::VulkanDispatch &vk, VkDevice device, VkPhysicalDevice physicalDevice, VkQueue queue, std::shared_ptr queueLock, VkCommandPool commandPool) : m_vk(vk), m_vkDevice(device), m_vkPhysicalDevice(physicalDevice), m_vkQueue(queue), m_vkQueueLock(queueLock), m_vkDescriptorSetLayout(VK_NULL_HANDLE), m_vkPipelineLayout(VK_NULL_HANDLE), m_vkRenderPass(VK_NULL_HANDLE), m_graphicsVkPipeline(VK_NULL_HANDLE), m_vertexVkBuffer(VK_NULL_HANDLE), m_vertexVkDeviceMemory(VK_NULL_HANDLE), m_indexVkBuffer(VK_NULL_HANDLE), m_indexVkDeviceMemory(VK_NULL_HANDLE), m_vkDescriptorPool(VK_NULL_HANDLE), m_vkDescriptorSets(0), m_vkCommandPool(commandPool) {} }; class CompositorVk : protected CompositorVkBase { public: static std::unique_ptr create( const goldfish_vk::VulkanDispatch &vk, VkDevice, VkPhysicalDevice, VkQueue, std::shared_ptr queueLock, VkFormat, VkImageLayout initialLayout, VkImageLayout finalLayout, uint32_t maxFramesInFlight, VkCommandPool, VkSampler); static bool validateQueueFamilyProperties(const VkQueueFamilyProperties &properties); ~CompositorVk(); void recordCommandBuffers(uint32_t renderTargetIndex, VkCommandBuffer, const CompositorVkRenderTarget &); void setComposition(uint32_t i, std::unique_ptr &&composition); std::unique_ptr createRenderTarget(VkImageView, uint32_t width, uint32_t height); private: explicit CompositorVk(const goldfish_vk::VulkanDispatch &, VkDevice, VkPhysicalDevice, VkQueue, std::shared_ptr queueLock, VkCommandPool, uint32_t maxFramesInFlight); void setUpGraphicsPipeline(VkFormat renderTargetFormat, VkImageLayout initialLayout, VkImageLayout finalLayout, VkSampler); void setUpVertexBuffers(); void setUpDescriptorSets(); void setUpEmptyComposition(VkFormat); void setUpUniformBuffers(); std::optional> createBuffer(VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags) const; std::tuple createStagingBufferWithData(const void *data, VkDeviceSize size) const; void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize) const; struct UniformBufferObject { alignas(16) glm::mat4 pos_transform; alignas(16) glm::mat4 texcoord_transform; }; struct Vertex { alignas(8) glm::vec2 pos; alignas(8) glm::vec2 texPos; static VkVertexInputBindingDescription getBindingDescription(); static std::array getAttributeDescription(); }; static const std::vector k_vertices; static const std::vector k_indices; uint32_t m_maxFramesInFlight; VkSampler m_vkSampler; std::vector> m_currentCompositions; struct UniformStorage { VkBuffer m_vkBuffer; VkDeviceMemory m_vkDeviceMemory; void *m_data; VkDeviceSize m_stride; } m_uniformStorage; }; class CompositorVkRenderTarget { public: ~CompositorVkRenderTarget(); private: const goldfish_vk::VulkanDispatch &m_vk; VkDevice m_vkDevice; VkFramebuffer m_vkFramebuffer; uint32_t m_width; uint32_t m_height; CompositorVkRenderTarget(const goldfish_vk::VulkanDispatch &, VkDevice, VkImageView, uint32_t width, uint32_t height, VkRenderPass); friend class CompositorVk; }; #endif /* COMPOSITOR_VK_H */