blob: 97a21a2dd0a106b63b5ff67d97efcacb9e2a3d8d [file] [log] [blame]
#ifndef COMPOSITOR_VK_H
#define COMPOSITOR_VK_H
#include <array>
#include <glm/glm.hpp>
#include <memory>
#include <optional>
#include <tuple>
#include <variant>
#include <vector>
#include "vulkan/cereal/common/goldfish_vk_dispatch.h"
#include "vulkan/vk_util.h"
#include "Hwc2.h"
class ComposeLayerVk {
public:
VkSampler m_vkSampler;
VkImageView m_vkImageView;
struct LayerTransform {
glm::mat4 pos;
glm::mat4 texcoord;
} m_layerTransform;
static std::unique_ptr<ComposeLayerVk> 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<std::unique_ptr<ComposeLayerVk>> m_composeLayers;
Composition() = delete;
explicit Composition(
std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers);
};
struct CompositorVkBase
: public vk_util::RunSingleTimeCommand<
CompositorVkBase,
vk_util::FindMemoryType<
CompositorVkBase,
vk_util::RecordImageLayoutTransformCommands<CompositorVkBase>>> {
const goldfish_vk::VulkanDispatch &m_vk;
const VkDevice m_vkDevice;
const VkPhysicalDevice m_vkPhysicalDevice;
const VkQueue m_vkQueue;
VkDescriptorSetLayout m_vkDescriptorSetLayout;
VkPipelineLayout m_vkPipelineLayout;
VkRenderPass m_vkRenderPass;
VkPipeline m_graphicsVkPipeline;
VkBuffer m_vertexVkBuffer;
VkDeviceMemory m_vertexVkDeviceMemory;
VkBuffer m_indexVkBuffer;
VkDeviceMemory m_indexVkDeviceMemory;
std::vector<VkCommandBuffer> m_vkCommandBuffers;
VkDescriptorPool m_vkDescriptorPool;
std::vector<VkDescriptorSet> m_vkDescriptorSets;
std::vector<VkFramebuffer> m_renderTargetVkFrameBuffers;
VkCommandPool m_vkCommandPool;
explicit CompositorVkBase(const goldfish_vk::VulkanDispatch &vk,
VkDevice device, VkPhysicalDevice physicalDevice,
VkQueue queue, VkCommandPool commandPool)
: m_vk(vk),
m_vkDevice(device),
m_vkPhysicalDevice(physicalDevice),
m_vkQueue(queue),
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_vkCommandBuffers(0),
m_vkDescriptorPool(VK_NULL_HANDLE),
m_vkDescriptorSets(0),
m_renderTargetVkFrameBuffers(0),
m_vkCommandPool(commandPool) {}
};
class CompositorVk : protected CompositorVkBase {
public:
static std::unique_ptr<CompositorVk> create(
const goldfish_vk::VulkanDispatch &vk, VkDevice, VkPhysicalDevice,
VkQueue, VkFormat, VkImageLayout initialLayout,
VkImageLayout finalLayout, uint32_t width, uint32_t height,
const std::vector<VkImageView> &renderTargets, VkCommandPool);
static bool validatePhysicalDeviceFeatures(
const VkPhysicalDeviceFeatures2 &features);
static bool validateQueueFamilyProperties(
const VkQueueFamilyProperties &properties);
static bool enablePhysicalDeviceFeatures(
VkPhysicalDeviceFeatures2 &features);
static std::vector<const char *> getRequiredDeviceExtensions();
~CompositorVk();
VkCommandBuffer getCommandBuffer(uint32_t i) const;
void setComposition(uint32_t i, std::unique_ptr<Composition> &&composition);
private:
explicit CompositorVk(const goldfish_vk::VulkanDispatch &, VkDevice,
VkPhysicalDevice, VkQueue, VkCommandPool,
uint32_t renderTargetWidth,
uint32_t renderTargetHeight);
void setUpGraphicsPipeline(uint32_t width, uint32_t height,
VkFormat renderTargetFormat,
VkImageLayout initialLayout,
VkImageLayout finalLayout);
void setUpVertexBuffers();
void setUpFramebuffers(const std::vector<VkImageView> &, uint32_t width,
uint32_t height);
void setUpDescriptorSets();
void setUpCommandBuffers(uint32_t width, uint32_t height);
void setUpEmptyComposition(VkFormat);
void setUpUniformBuffers();
std::optional<std::tuple<VkBuffer, VkDeviceMemory>> createBuffer(
VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags) const;
std::tuple<VkBuffer, VkDeviceMemory> 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<VkVertexInputAttributeDescription, 2>
getAttributeDescription();
};
static const std::vector<Vertex> k_vertices;
static const std::vector<uint16_t> k_indices;
static const VkExtent2D k_emptyCompositionExtent;
uint32_t m_renderTargetWidth;
uint32_t m_renderTargetHeight;
VkImage m_emptyCompositionVkImage;
VkDeviceMemory m_emptyCompositionVkDeviceMemory;
VkImageView m_emptyCompositionVkImageView;
VkSampler m_emptyCompositionVkSampler;
std::vector<std::unique_ptr<Composition>> m_currentCompositions;
struct UniformStorage {
VkBuffer m_vkBuffer;
VkDeviceMemory m_vkDeviceMemory;
void *m_data;
VkDeviceSize m_stride;
} m_uniformStorage;
};
#endif /* COMPOSITOR_VK_H */