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, ©Region);
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 ¤tComposition = *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 }