• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "CompositorVk.h"
2 
3 #include <string.h>
4 
5 #include <cinttypes>
6 #include <glm/gtc/matrix_transform.hpp>
7 #include <optional>
8 
9 #include "host-common/logging.h"
10 #include "vulkan/VkCommonOperations.h"
11 #include "vulkan/vk_util.h"
12 
13 using emugl::ABORT_REASON_OTHER;
14 using emugl::FatalError;
15 
16 namespace CompositorVkShader {
17 #include "vulkan/CompositorFragmentShader.h"
18 #include "vulkan/CompositorVertexShader.h"
19 }  // namespace CompositorVkShader
20 
21 #define COMPOSITOR_VK_ERROR(fmt, ...)                                                         \
22     do {                                                                                      \
23         fprintf(stderr, "%s(%s:%d): " fmt "\n", __func__, __FILE__, __LINE__, ##__VA_ARGS__); \
24         fflush(stderr);                                                                       \
25     } while (0)
26 
createShaderModule(const goldfish_vk::VulkanDispatch & vk,VkDevice device,const std::vector<uint32_t> & code)27 static VkShaderModule createShaderModule(const goldfish_vk::VulkanDispatch &vk, VkDevice device,
28                                          const std::vector<uint32_t> &code) {
29     VkShaderModuleCreateInfo shaderModuleCi = {
30         .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
31         .codeSize = static_cast<uint32_t>(code.size() * sizeof(uint32_t)),
32         .pCode = code.data()};
33     VkShaderModule res;
34     VK_CHECK(vk.vkCreateShaderModule(device, &shaderModuleCi, nullptr, &res));
35     return res;
36 }
37 
ComposeLayerVk(VkSampler vkSampler,VkImageView vkImageView,const LayerTransform & layerTransform)38 ComposeLayerVk::ComposeLayerVk(VkSampler vkSampler, VkImageView vkImageView,
39                                const LayerTransform &layerTransform)
40     : m_vkSampler(vkSampler),
41       m_vkImageView(vkImageView),
42       m_layerTransform({.pos = layerTransform.pos, .texcoord = layerTransform.texcoord}) {}
43 
createFromHwc2ComposeLayer(VkSampler vkSampler,VkImageView vkImageView,const ComposeLayer & composeLayer,uint32_t cbWidth,uint32_t cbHeight,uint32_t dstWidth,uint32_t dstHeight)44 std::unique_ptr<ComposeLayerVk> ComposeLayerVk::createFromHwc2ComposeLayer(
45     VkSampler vkSampler, VkImageView vkImageView, const ComposeLayer &composeLayer,
46     uint32_t cbWidth, uint32_t cbHeight, uint32_t dstWidth, uint32_t dstHeight) {
47     // Calculate the posTransform and the texcoordTransform needed in the
48     // uniform of the Compositor.vert shader. The posTransform should transform
49     // the square(top = -1, bottom = 1, left = -1, right = 1) to the position
50     // where the layer should be drawn in NDC space given the composeLayer.
51     // texcoordTransform should transform the unit square(top = 0, bottom = 1,
52     // left = 0, right = 1) to where we should sample the layer in the
53     // normalized uv space given the composeLayer.
54     const hwc_rect_t &posRect = composeLayer.displayFrame;
55     const hwc_frect_t &texcoordRect = composeLayer.crop;
56 
57     int posWidth = posRect.right - posRect.left;
58     int posHeight = posRect.bottom - posRect.top;
59 
60     float posScaleX = float(posWidth) / dstWidth;
61     float posScaleY = float(posHeight) / dstHeight;
62 
63     float posTranslateX = -1.0f + posScaleX + 2.0f * float(posRect.left) / dstWidth;
64     float posTranslateY = -1.0f + posScaleY + 2.0f * float(posRect.top) / dstHeight;
65 
66     float texcoordScalX = (texcoordRect.right - texcoordRect.left) / float(cbWidth);
67     float texCoordScaleY = (texcoordRect.bottom - texcoordRect.top) / float(cbHeight);
68 
69     float texCoordTranslateX = texcoordRect.left / float(cbWidth);
70     float texCoordTranslateY = texcoordRect.top / float(cbHeight);
71 
72     float texcoordRotation = 0.0f;
73 
74     const float pi = glm::pi<float>();
75 
76     switch (composeLayer.transform) {
77         case HWC_TRANSFORM_ROT_90:
78             texcoordRotation = pi * 0.5f;
79             break;
80         case HWC_TRANSFORM_ROT_180:
81             texcoordRotation = pi;
82             break;
83         case HWC_TRANSFORM_ROT_270:
84             texcoordRotation = pi * 1.5f;
85             break;
86         case HWC_TRANSFORM_FLIP_H:
87             texcoordScalX *= -1.0f;
88             break;
89         case HWC_TRANSFORM_FLIP_V:
90             texCoordScaleY *= -1.0f;
91             break;
92         case HWC_TRANSFORM_FLIP_H_ROT_90:
93             texcoordRotation = pi * 0.5f;
94             texcoordScalX *= -1.0f;
95             break;
96         case HWC_TRANSFORM_FLIP_V_ROT_90:
97             texcoordRotation = pi * 0.5f;
98             texCoordScaleY *= -1.0f;
99             break;
100         default:
101             break;
102     }
103 
104     ComposeLayerVk::LayerTransform layerTransform = {
105         .pos = glm::translate(glm::mat4(1.0f), glm::vec3(posTranslateX, posTranslateY, 0.0f)) *
106                glm::scale(glm::mat4(1.0f), glm::vec3(posScaleX, posScaleY, 1.0f)),
107         .texcoord = glm::translate(glm::mat4(1.0f),
108                                    glm::vec3(texCoordTranslateX, texCoordTranslateY, 0.0f)) *
109                     glm::scale(glm::mat4(1.0f), glm::vec3(texcoordScalX, texCoordScaleY, 1.0f)) *
110                     glm::rotate(glm::mat4(1.0f), texcoordRotation, glm::vec3(0.0f, 0.0f, 1.0f)),
111     };
112 
113     return std::unique_ptr<ComposeLayerVk>(
114         new ComposeLayerVk(vkSampler, vkImageView, layerTransform));
115 }
116 
Composition(std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers)117 Composition::Composition(std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers)
118     : m_composeLayers(std::move(composeLayers)) {}
119 
120 const std::vector<CompositorVk::Vertex> CompositorVk::k_vertices = {
121     {{-1.0f, -1.0f}, {0.0f, 0.0f}},
122     {{1.0f, -1.0f}, {1.0f, 0.0f}},
123     {{1.0f, 1.0f}, {1.0f, 1.0f}},
124     {{-1.0f, 1.0f}, {0.0f, 1.0f}},
125 };
126 
127 const std::vector<uint16_t> CompositorVk::k_indices = {0, 1, 2, 2, 3, 0};
128 
create(const goldfish_vk::VulkanDispatch & vk,VkDevice vkDevice,VkPhysicalDevice vkPhysicalDevice,VkQueue vkQueue,std::shared_ptr<android::base::Lock> queueLock,VkFormat format,VkImageLayout initialLayout,VkImageLayout finalLayout,uint32_t maxFramesInFlight,VkCommandPool commandPool,VkSampler sampler)129 std::unique_ptr<CompositorVk> CompositorVk::create(
130     const goldfish_vk::VulkanDispatch &vk, VkDevice vkDevice, VkPhysicalDevice vkPhysicalDevice,
131     VkQueue vkQueue, std::shared_ptr<android::base::Lock> queueLock, VkFormat format,
132     VkImageLayout initialLayout, VkImageLayout finalLayout, uint32_t maxFramesInFlight,
133     VkCommandPool commandPool, VkSampler sampler) {
134     auto res = std::unique_ptr<CompositorVk>(new CompositorVk(
135         vk, vkDevice, vkPhysicalDevice, vkQueue, queueLock, commandPool, maxFramesInFlight));
136     res->setUpGraphicsPipeline(format, initialLayout, finalLayout, sampler);
137     res->m_vkSampler = sampler;
138     res->setUpVertexBuffers();
139     res->setUpUniformBuffers();
140     res->setUpDescriptorSets();
141     res->m_currentCompositions.resize(maxFramesInFlight);
142     for (auto i = 0; i < maxFramesInFlight; i++) {
143         std::vector<std::unique_ptr<ComposeLayerVk>> emptyCompositionLayers;
144         res->setComposition(i, std::make_unique<Composition>(std::move(emptyCompositionLayers)));
145     }
146     return res;
147 }
148 
CompositorVk(const goldfish_vk::VulkanDispatch & vk,VkDevice vkDevice,VkPhysicalDevice vkPhysicalDevice,VkQueue vkQueue,std::shared_ptr<android::base::Lock> queueLock,VkCommandPool commandPool,uint32_t maxFramesInFlight)149 CompositorVk::CompositorVk(const goldfish_vk::VulkanDispatch &vk, VkDevice vkDevice,
150                            VkPhysicalDevice vkPhysicalDevice, VkQueue vkQueue,
151                            std::shared_ptr<android::base::Lock> queueLock,
152                            VkCommandPool commandPool, uint32_t maxFramesInFlight)
153     : CompositorVkBase(vk, vkDevice, vkPhysicalDevice, vkQueue, queueLock, commandPool),
154       m_maxFramesInFlight(maxFramesInFlight),
155       m_vkSampler(VK_NULL_HANDLE),
156       m_currentCompositions(0),
157       m_uniformStorage({VK_NULL_HANDLE, VK_NULL_HANDLE, nullptr, 0}) {
158     VkPhysicalDeviceProperties physicalDeviceProperties;
159     m_vk.vkGetPhysicalDeviceProperties(m_vkPhysicalDevice, &physicalDeviceProperties);
160     auto alignment = physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
161     m_uniformStorage.m_stride = ((sizeof(UniformBufferObject) - 1) / alignment + 1) * alignment;
162 }
163 
~CompositorVk()164 CompositorVk::~CompositorVk() {
165     m_vk.vkDestroyDescriptorPool(m_vkDevice, m_vkDescriptorPool, nullptr);
166     if (m_uniformStorage.m_vkDeviceMemory != VK_NULL_HANDLE) {
167         m_vk.vkUnmapMemory(m_vkDevice, m_uniformStorage.m_vkDeviceMemory);
168     }
169     m_vk.vkDestroyBuffer(m_vkDevice, m_uniformStorage.m_vkBuffer, nullptr);
170     m_vk.vkFreeMemory(m_vkDevice, m_uniformStorage.m_vkDeviceMemory, nullptr);
171     m_vk.vkFreeMemory(m_vkDevice, m_vertexVkDeviceMemory, nullptr);
172     m_vk.vkDestroyBuffer(m_vkDevice, m_vertexVkBuffer, nullptr);
173     m_vk.vkFreeMemory(m_vkDevice, m_indexVkDeviceMemory, nullptr);
174     m_vk.vkDestroyBuffer(m_vkDevice, m_indexVkBuffer, nullptr);
175     m_vk.vkDestroyPipeline(m_vkDevice, m_graphicsVkPipeline, nullptr);
176     m_vk.vkDestroyRenderPass(m_vkDevice, m_vkRenderPass, nullptr);
177     m_vk.vkDestroyPipelineLayout(m_vkDevice, m_vkPipelineLayout, nullptr);
178     m_vk.vkDestroyDescriptorSetLayout(m_vkDevice, m_vkDescriptorSetLayout, nullptr);
179 }
180 
setUpGraphicsPipeline(VkFormat renderTargetFormat,VkImageLayout initialLayout,VkImageLayout finalLayout,VkSampler sampler)181 void CompositorVk::setUpGraphicsPipeline(VkFormat renderTargetFormat, VkImageLayout initialLayout,
182                                          VkImageLayout finalLayout, VkSampler sampler) {
183     const std::vector<uint32_t> vertSpvBuff(CompositorVkShader::compositorVertexShader,
184                                             std::end(CompositorVkShader::compositorVertexShader));
185     const std::vector<uint32_t> fragSpvBuff(CompositorVkShader::compositorFragmentShader,
186                                             std::end(CompositorVkShader::compositorFragmentShader));
187     const auto vertShaderMod = createShaderModule(m_vk, m_vkDevice, vertSpvBuff);
188     const auto fragShaderMod = createShaderModule(m_vk, m_vkDevice, fragSpvBuff);
189 
190     VkPipelineShaderStageCreateInfo shaderStageCis[2] = {
191         {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
192          .stage = VK_SHADER_STAGE_VERTEX_BIT,
193          .module = vertShaderMod,
194          .pName = "main"},
195         {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
196          .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
197          .module = fragShaderMod,
198          .pName = "main"}};
199 
200     auto bindingDescription = Vertex::getBindingDescription();
201     auto attributeDescription = Vertex::getAttributeDescription();
202     VkPipelineVertexInputStateCreateInfo vertexInputStateCi = {
203         .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
204         .vertexBindingDescriptionCount = 1,
205         .pVertexBindingDescriptions = &bindingDescription,
206         .vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescription.size()),
207         .pVertexAttributeDescriptions = attributeDescription.data()};
208     VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCi = {
209         .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
210         .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
211         .primitiveRestartEnable = VK_FALSE,
212     };
213 
214     VkPipelineViewportStateCreateInfo viewportStateCi = {
215         .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
216         .viewportCount = 1,
217         // The viewport state is dynamic.
218         .pViewports = nullptr,
219         .scissorCount = 1,
220         // The scissor state is dynamic.
221         .pScissors = nullptr,
222     };
223 
224     VkPipelineRasterizationStateCreateInfo rasterizerStateCi = {
225         .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
226         .depthClampEnable = VK_FALSE,
227         .rasterizerDiscardEnable = VK_FALSE,
228         .polygonMode = VK_POLYGON_MODE_FILL,
229         .cullMode = VK_CULL_MODE_BACK_BIT,
230         .frontFace = VK_FRONT_FACE_CLOCKWISE,
231         .depthBiasEnable = VK_FALSE,
232         .depthBiasConstantFactor = 0.0f,
233         .depthBiasClamp = 0.0f,
234         .depthBiasSlopeFactor = 0.0f,
235         .lineWidth = 1.0f};
236 
237     VkPipelineMultisampleStateCreateInfo multisampleStateCi = {
238         .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
239         .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
240         .sampleShadingEnable = VK_FALSE,
241         .minSampleShading = 1.0f,
242         .pSampleMask = nullptr,
243         .alphaToCoverageEnable = VK_FALSE,
244         .alphaToOneEnable = VK_FALSE};
245 
246     VkPipelineColorBlendAttachmentState colorBlendAttachment = {
247         .blendEnable = VK_TRUE,
248         .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
249         .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
250         .colorBlendOp = VK_BLEND_OP_ADD,
251         .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
252         .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
253         .alphaBlendOp = VK_BLEND_OP_ADD,
254         .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
255                           VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
256 
257     VkPipelineColorBlendStateCreateInfo colorBlendStateCi = {
258         .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
259         .logicOpEnable = VK_FALSE,
260         .attachmentCount = 1,
261         .pAttachments = &colorBlendAttachment};
262 
263     VkDynamicState dynamicStates[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
264     VkPipelineDynamicStateCreateInfo dynamicStateCi = {
265         .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
266         .dynamicStateCount = std::size(dynamicStates),
267         .pDynamicStates = dynamicStates,
268     };
269 
270     VkDescriptorSetLayoutBinding layoutBindings[2] = {
271         {.binding = 0,
272          .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
273          .descriptorCount = 1,
274          .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
275          .pImmutableSamplers = &sampler},
276         {.binding = 1,
277          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
278          .descriptorCount = 1,
279          .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
280          .pImmutableSamplers = nullptr}};
281 
282     VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCi = {
283         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
284         .pNext = nullptr,
285         .flags = 0,
286         .bindingCount = static_cast<uint32_t>(std::size(layoutBindings)),
287         .pBindings = layoutBindings};
288     VK_CHECK(m_vk.vkCreateDescriptorSetLayout(m_vkDevice, &descriptorSetLayoutCi, nullptr,
289                                               &m_vkDescriptorSetLayout));
290 
291     VkPipelineLayoutCreateInfo pipelineLayoutCi = {
292         .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
293         .setLayoutCount = 1,
294         .pSetLayouts = &m_vkDescriptorSetLayout,
295         .pushConstantRangeCount = 0};
296 
297     VK_CHECK(
298         m_vk.vkCreatePipelineLayout(m_vkDevice, &pipelineLayoutCi, nullptr, &m_vkPipelineLayout));
299 
300     VkAttachmentDescription colorAttachment = {.format = renderTargetFormat,
301                                                .samples = VK_SAMPLE_COUNT_1_BIT,
302                                                .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
303                                                .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
304                                                .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
305                                                .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
306                                                .initialLayout = initialLayout,
307                                                .finalLayout = finalLayout};
308 
309     VkAttachmentReference colorAttachmentRef = {.attachment = 0,
310                                                 .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
311 
312     VkSubpassDescription subpass = {.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
313                                     .colorAttachmentCount = 1,
314                                     .pColorAttachments = &colorAttachmentRef};
315 
316     // TODO: to support multiple layer composition, we could run the same render
317     // pass for multiple time. In that case, we should use explicit
318     // VkImageMemoryBarriers to transform the image layout instead of relying on
319     // renderpass to do it.
320     VkSubpassDependency subpassDependency = {
321         .srcSubpass = VK_SUBPASS_EXTERNAL,
322         .dstSubpass = 0,
323         .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
324         .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
325         .srcAccessMask = 0,
326         .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
327 
328     VkRenderPassCreateInfo renderPassCi = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
329                                            .attachmentCount = 1,
330                                            .pAttachments = &colorAttachment,
331                                            .subpassCount = 1,
332                                            .pSubpasses = &subpass,
333                                            .dependencyCount = 1,
334                                            .pDependencies = &subpassDependency};
335 
336     VK_CHECK(m_vk.vkCreateRenderPass(m_vkDevice, &renderPassCi, nullptr, &m_vkRenderPass));
337 
338     VkGraphicsPipelineCreateInfo graphicsPipelineCi = {
339         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
340         .stageCount = static_cast<uint32_t>(std::size(shaderStageCis)),
341         .pStages = shaderStageCis,
342         .pVertexInputState = &vertexInputStateCi,
343         .pInputAssemblyState = &inputAssemblyStateCi,
344         .pViewportState = &viewportStateCi,
345         .pRasterizationState = &rasterizerStateCi,
346         .pMultisampleState = &multisampleStateCi,
347         .pDepthStencilState = nullptr,
348         .pColorBlendState = &colorBlendStateCi,
349         .pDynamicState = &dynamicStateCi,
350         .layout = m_vkPipelineLayout,
351         .renderPass = m_vkRenderPass,
352         .subpass = 0,
353         .basePipelineHandle = VK_NULL_HANDLE,
354         .basePipelineIndex = -1};
355 
356     VK_CHECK(m_vk.vkCreateGraphicsPipelines(m_vkDevice, VK_NULL_HANDLE, 1, &graphicsPipelineCi,
357                                             nullptr, &m_graphicsVkPipeline));
358 
359     m_vk.vkDestroyShaderModule(m_vkDevice, vertShaderMod, nullptr);
360     m_vk.vkDestroyShaderModule(m_vkDevice, fragShaderMod, nullptr);
361 }
362 
363 // Create a VkBuffer and a bound VkDeviceMemory. When the specified memory type
364 // can't be found, return std::nullopt. When Vulkan call fails, terminate the
365 // program.
createBuffer(VkDeviceSize size,VkBufferUsageFlags usage,VkMemoryPropertyFlags memProperty) const366 std::optional<std::tuple<VkBuffer, VkDeviceMemory>> CompositorVk::createBuffer(
367     VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memProperty) const {
368     VkBufferCreateInfo bufferCi = {.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
369                                    .size = size,
370                                    .usage = usage,
371                                    .sharingMode = VK_SHARING_MODE_EXCLUSIVE};
372     VkBuffer resBuffer;
373     VK_CHECK(m_vk.vkCreateBuffer(m_vkDevice, &bufferCi, nullptr, &resBuffer));
374     VkMemoryRequirements memRequirements;
375     m_vk.vkGetBufferMemoryRequirements(m_vkDevice, resBuffer, &memRequirements);
376     VkPhysicalDeviceMemoryProperties physicalMemProperties;
377     m_vk.vkGetPhysicalDeviceMemoryProperties(m_vkPhysicalDevice, &physicalMemProperties);
378     auto maybeMemoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, memProperty);
379     if (!maybeMemoryTypeIndex.has_value()) {
380         m_vk.vkDestroyBuffer(m_vkDevice, resBuffer, nullptr);
381         return std::nullopt;
382     }
383     VkMemoryAllocateInfo memAllocInfo = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
384                                          .allocationSize = memRequirements.size,
385                                          .memoryTypeIndex = maybeMemoryTypeIndex.value()};
386     VkDeviceMemory resMemory;
387     VK_CHECK(m_vk.vkAllocateMemory(m_vkDevice, &memAllocInfo, nullptr, &resMemory));
388     VK_CHECK(m_vk.vkBindBufferMemory(m_vkDevice, resBuffer, resMemory, 0));
389     return std::make_tuple(resBuffer, resMemory);
390 }
391 
createStagingBufferWithData(const void * srcData,VkDeviceSize size) const392 std::tuple<VkBuffer, VkDeviceMemory> CompositorVk::createStagingBufferWithData(
393     const void *srcData, VkDeviceSize size) const {
394     auto [stagingBuffer, stagingBufferMemory] =
395         createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
396                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
397             .value();
398     void *data;
399     VK_CHECK(m_vk.vkMapMemory(m_vkDevice, stagingBufferMemory, 0, size, 0, &data));
400     memcpy(data, srcData, size);
401     m_vk.vkUnmapMemory(m_vkDevice, stagingBufferMemory);
402     return std::make_tuple(stagingBuffer, stagingBufferMemory);
403 }
404 
copyBuffer(VkBuffer src,VkBuffer dst,VkDeviceSize size) const405 void CompositorVk::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) const {
406     runSingleTimeCommands(m_vkQueue, m_vkQueueLock, [&, this](const auto &cmdBuff) {
407         VkBufferCopy copyRegion = {};
408         copyRegion.srcOffset = 0;
409         copyRegion.dstOffset = 0;
410         copyRegion.size = size;
411         m_vk.vkCmdCopyBuffer(cmdBuff, src, dst, 1, &copyRegion);
412     });
413 }
414 
setUpVertexBuffers()415 void CompositorVk::setUpVertexBuffers() {
416     const VkDeviceSize vertexBufferSize = sizeof(k_vertices[0]) * k_vertices.size();
417     std::tie(m_vertexVkBuffer, m_vertexVkDeviceMemory) =
418         createBuffer(vertexBufferSize,
419                      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
420                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
421             .value();
422     auto [vertexStagingBuffer, vertexStagingBufferMemory] =
423         createStagingBufferWithData(k_vertices.data(), vertexBufferSize);
424     copyBuffer(vertexStagingBuffer, m_vertexVkBuffer, vertexBufferSize);
425     m_vk.vkDestroyBuffer(m_vkDevice, vertexStagingBuffer, nullptr);
426     m_vk.vkFreeMemory(m_vkDevice, vertexStagingBufferMemory, nullptr);
427 
428     VkDeviceSize indexBufferSize = sizeof(k_indices[0]) * k_indices.size();
429     auto [indexStagingBuffer, indexStagingBufferMemory] =
430         createStagingBufferWithData(k_indices.data(), indexBufferSize);
431     std::tie(m_indexVkBuffer, m_indexVkDeviceMemory) =
432         createBuffer(indexBufferSize,
433                      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
434                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
435             .value();
436     copyBuffer(indexStagingBuffer, m_indexVkBuffer, indexBufferSize);
437     m_vk.vkDestroyBuffer(m_vkDevice, indexStagingBuffer, nullptr);
438     m_vk.vkFreeMemory(m_vkDevice, indexStagingBufferMemory, nullptr);
439 }
440 
441 // We do see a composition requests with 12 layers. (b/222700096)
442 // Inside hwc2, we will ask for surfaceflinger to
443 // do the composition, if the layers more than 16.
444 // If we see rendering error or significant time spent on updating
445 // descriptors in setComposition, we should tune this number.
446 static const uint32_t kMaxLayersPerFrame = 16;
447 
setUpDescriptorSets()448 void CompositorVk::setUpDescriptorSets() {
449     uint32_t setsPerDescriptorType = m_maxFramesInFlight * kMaxLayersPerFrame;
450 
451     VkDescriptorPoolSize descriptorPoolSizes[2] = {
452         {.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
453          .descriptorCount = setsPerDescriptorType},
454         {.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = setsPerDescriptorType}};
455 
456     VkDescriptorPoolCreateInfo descriptorPoolCi = {
457         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
458         .flags = 0,
459         .maxSets = static_cast<uint32_t>(setsPerDescriptorType),
460         .poolSizeCount = static_cast<uint32_t>(std::size(descriptorPoolSizes)),
461         .pPoolSizes = descriptorPoolSizes};
462     VK_CHECK(
463         m_vk.vkCreateDescriptorPool(m_vkDevice, &descriptorPoolCi, nullptr, &m_vkDescriptorPool));
464     std::vector<VkDescriptorSetLayout> layouts(setsPerDescriptorType, m_vkDescriptorSetLayout);
465     VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {
466         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
467         .descriptorPool = m_vkDescriptorPool,
468         .descriptorSetCount = setsPerDescriptorType,
469         .pSetLayouts = layouts.data()};
470     m_vkDescriptorSets.resize(setsPerDescriptorType);
471     VK_CHECK(m_vk.vkAllocateDescriptorSets(m_vkDevice, &descriptorSetAllocInfo,
472                                            m_vkDescriptorSets.data()));
473     for (size_t i = 0; i < setsPerDescriptorType; i++) {
474         VkDescriptorBufferInfo bufferInfo = {.buffer = m_uniformStorage.m_vkBuffer,
475                                              .offset = i * m_uniformStorage.m_stride,
476                                              .range = sizeof(UniformBufferObject)};
477         VkWriteDescriptorSet descriptorSetWrite = {
478             .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
479             .dstSet = m_vkDescriptorSets[i],
480             .dstBinding = 1,
481             .dstArrayElement = 0,
482             .descriptorCount = 1,
483             .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
484             .pBufferInfo = &bufferInfo};
485         m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0, nullptr);
486     }
487 }
488 
recordCommandBuffers(uint32_t renderTargetIndex,VkCommandBuffer cmdBuffer,const CompositorVkRenderTarget & renderTarget)489 void CompositorVk::recordCommandBuffers(uint32_t renderTargetIndex, VkCommandBuffer cmdBuffer,
490                                         const CompositorVkRenderTarget &renderTarget) {
491     VkClearValue clearColor = {.color = {.float32 = {0.0f, 0.0f, 0.0f, 1.0f}}};
492     VkRenderPassBeginInfo renderPassBeginInfo = {
493         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
494         .renderPass = m_vkRenderPass,
495         .framebuffer = renderTarget.m_vkFramebuffer,
496         .renderArea = {.offset = {0, 0}, .extent = {renderTarget.m_width, renderTarget.m_height}},
497         .clearValueCount = 1,
498         .pClearValues = &clearColor};
499     m_vk.vkCmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
500     m_vk.vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsVkPipeline);
501     VkRect2D scissor = {
502         .offset = {0, 0},
503         .extent =
504             {
505                 .width = renderTarget.m_width,
506                 .height = renderTarget.m_height,
507             },
508     };
509     m_vk.vkCmdSetScissor(cmdBuffer, 0, 1, &scissor);
510     VkViewport viewport = {
511         .x = 0.0f,
512         .y = 0.0f,
513         .width = static_cast<float>(renderTarget.m_width),
514         .height = static_cast<float>(renderTarget.m_height),
515         .minDepth = 0.0f,
516         .maxDepth = 1.0f,
517     };
518     m_vk.vkCmdSetViewport(cmdBuffer, 0, 1, &viewport);
519     VkDeviceSize offsets[] = {0};
520     m_vk.vkCmdBindVertexBuffers(cmdBuffer, 0, 1, &m_vertexVkBuffer, offsets);
521     m_vk.vkCmdBindIndexBuffer(cmdBuffer, m_indexVkBuffer, 0, VK_INDEX_TYPE_UINT16);
522     for (uint32_t j = 0; j < m_currentCompositions[renderTargetIndex]->m_composeLayers.size();
523          ++j) {
524         m_vk.vkCmdBindDescriptorSets(
525             cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_vkPipelineLayout, 0, 1,
526             &m_vkDescriptorSets[renderTargetIndex * kMaxLayersPerFrame + j], 0, nullptr);
527         m_vk.vkCmdDrawIndexed(cmdBuffer, static_cast<uint32_t>(k_indices.size()), 1, 0, 0, 0);
528     }
529     m_vk.vkCmdEndRenderPass(cmdBuffer);
530 }
531 
setUpUniformBuffers()532 void CompositorVk::setUpUniformBuffers() {
533     VkDeviceSize size = m_uniformStorage.m_stride * m_maxFramesInFlight * kMaxLayersPerFrame;
534     auto maybeBuffer =
535         createBuffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
536                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
537                          VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
538     auto buffer = std::make_tuple<VkBuffer, VkDeviceMemory>(VK_NULL_HANDLE, VK_NULL_HANDLE);
539     if (maybeBuffer.has_value()) {
540         buffer = maybeBuffer.value();
541     } else {
542         buffer =
543             createBuffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
544                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
545                 .value();
546     }
547     std::tie(m_uniformStorage.m_vkBuffer, m_uniformStorage.m_vkDeviceMemory) = buffer;
548     VK_CHECK(m_vk.vkMapMemory(m_vkDevice, m_uniformStorage.m_vkDeviceMemory, 0, size, 0,
549                               reinterpret_cast<void **>(&m_uniformStorage.m_data)));
550 }
551 
validateQueueFamilyProperties(const VkQueueFamilyProperties & properties)552 bool CompositorVk::validateQueueFamilyProperties(const VkQueueFamilyProperties &properties) {
553     return properties.queueFlags & VK_QUEUE_GRAPHICS_BIT;
554 }
555 
setComposition(uint32_t rtIndex,std::unique_ptr<Composition> && composition)556 void CompositorVk::setComposition(uint32_t rtIndex, std::unique_ptr<Composition> &&composition) {
557     m_currentCompositions[rtIndex] = std::move(composition);
558     const auto &currentComposition = *m_currentCompositions[rtIndex];
559     if (currentComposition.m_composeLayers.size() > kMaxLayersPerFrame) {
560         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
561             << "CompositorVk can't compose more than " << kMaxLayersPerFrame
562             << " layers. layers asked: "
563             << static_cast<uint32_t>(currentComposition.m_composeLayers.size());
564     }
565 
566     memset(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
567                (rtIndex * kMaxLayersPerFrame + 0) * m_uniformStorage.m_stride,
568            0, sizeof(ComposeLayerVk::LayerTransform) * kMaxLayersPerFrame);
569 
570     std::vector<VkDescriptorImageInfo> imageInfos(currentComposition.m_composeLayers.size());
571     std::vector<VkWriteDescriptorSet> descriptorWrites;
572     for (size_t i = 0; i < currentComposition.m_composeLayers.size(); ++i) {
573         const auto &layer = currentComposition.m_composeLayers[i];
574         if (m_vkSampler != layer->m_vkSampler) {
575             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
576                 << "Unsupported sampler(" << reinterpret_cast<uintptr_t>(layer->m_vkSampler)
577                 << ").";
578         }
579         imageInfos[i] =
580             VkDescriptorImageInfo({.sampler = VK_NULL_HANDLE,
581                                    .imageView = layer->m_vkImageView,
582                                    .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL});
583         const VkDescriptorImageInfo &imageInfo = imageInfos[i];
584         descriptorWrites.emplace_back(
585             VkWriteDescriptorSet{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
586                                   .dstSet = m_vkDescriptorSets[rtIndex * kMaxLayersPerFrame + i],
587                                   .dstBinding = 0,
588                                   .dstArrayElement = 0,
589                                   .descriptorCount = 1,
590                                   .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
591                                   .pImageInfo = &imageInfo});
592         memcpy(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
593                    (rtIndex * kMaxLayersPerFrame + i) * m_uniformStorage.m_stride,
594                &layer->m_layerTransform, sizeof(ComposeLayerVk::LayerTransform));
595     }
596     m_vk.vkUpdateDescriptorSets(m_vkDevice, descriptorWrites.size(), descriptorWrites.data(), 0,
597                                 nullptr);
598 }
599 
createRenderTarget(VkImageView vkImageView,uint32_t width,uint32_t height)600 std::unique_ptr<CompositorVkRenderTarget> CompositorVk::createRenderTarget(VkImageView vkImageView,
601                                                                            uint32_t width,
602                                                                            uint32_t height) {
603     return std::unique_ptr<CompositorVkRenderTarget>(
604         new CompositorVkRenderTarget(m_vk, m_vkDevice, vkImageView, width, height, m_vkRenderPass));
605 }
606 
getBindingDescription()607 VkVertexInputBindingDescription CompositorVk::Vertex::getBindingDescription() {
608     return {
609         .binding = 0, .stride = sizeof(struct Vertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX};
610 }
611 
getAttributeDescription()612 std::array<VkVertexInputAttributeDescription, 2> CompositorVk::Vertex::getAttributeDescription() {
613     return {VkVertexInputAttributeDescription{.location = 0,
614                                               .binding = 0,
615                                               .format = VK_FORMAT_R32G32_SFLOAT,
616                                               .offset = offsetof(struct Vertex, pos)},
617             VkVertexInputAttributeDescription{.location = 1,
618                                               .binding = 0,
619                                               .format = VK_FORMAT_R32G32_SFLOAT,
620                                               .offset = offsetof(struct Vertex, texPos)}};
621 }
622 
CompositorVkRenderTarget(const goldfish_vk::VulkanDispatch & vk,VkDevice vkDevice,VkImageView vkImageView,uint32_t width,uint32_t height,VkRenderPass vkRenderPass)623 CompositorVkRenderTarget::CompositorVkRenderTarget(const goldfish_vk::VulkanDispatch &vk,
624                                                    VkDevice vkDevice, VkImageView vkImageView,
625                                                    uint32_t width, uint32_t height,
626                                                    VkRenderPass vkRenderPass)
627     : m_vk(vk),
628       m_vkDevice(vkDevice),
629       m_vkFramebuffer(VK_NULL_HANDLE),
630       m_width(width),
631       m_height(height) {
632     VkFramebufferCreateInfo framebufferCi = {
633         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
634         .flags = 0,
635         .renderPass = vkRenderPass,
636         .attachmentCount = 1,
637         .pAttachments = &vkImageView,
638         .width = width,
639         .height = height,
640         .layers = 1,
641     };
642     VK_CHECK(m_vk.vkCreateFramebuffer(vkDevice, &framebufferCi, nullptr, &m_vkFramebuffer));
643 }
644 
~CompositorVkRenderTarget()645 CompositorVkRenderTarget::~CompositorVkRenderTarget() {
646     m_vk.vkDestroyFramebuffer(m_vkDevice, m_vkFramebuffer, nullptr);
647 }