• 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/vk_enum_string_helper.h"
11 #include "vulkan/vk_util.h"
12 
13 namespace gfxstream {
14 namespace vk {
15 
16 using emugl::ABORT_REASON_OTHER;
17 using emugl::FatalError;
18 
19 namespace CompositorVkShader {
20 #include "vulkan/CompositorFragmentShader.h"
21 #include "vulkan/CompositorVertexShader.h"
22 }  // namespace CompositorVkShader
23 
24 namespace {
25 
26 constexpr const VkImageLayout kSourceImageInitialLayoutUsed =
27     VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
28 constexpr const VkImageLayout kSourceImageFinalLayoutUsed =
29     VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
30 
31 constexpr const VkImageLayout kTargetImageInitialLayoutUsed = VK_IMAGE_LAYOUT_UNDEFINED;
32 constexpr const VkImageLayout kTargetImageFinalLayoutUsed = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
33 
getInfoOrAbort(const std::unique_ptr<BorrowedImageInfo> & info)34 const BorrowedImageInfoVk* getInfoOrAbort(const std::unique_ptr<BorrowedImageInfo>& info) {
35     auto imageVk = static_cast<const BorrowedImageInfoVk*>(info.get());
36     if (imageVk != nullptr) {
37         return imageVk;
38     }
39 
40     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
41         << "CompositorVk did not find BorrowedImageInfoVk";
42 }
43 
44 struct Vertex {
45     alignas(8) glm::vec2 pos;
46     alignas(8) glm::vec2 tex;
47 
getBindingDescriptiongfxstream::vk::__anon5852debb0111::Vertex48     static VkVertexInputBindingDescription getBindingDescription() {
49         return VkVertexInputBindingDescription{
50             .binding = 0,
51             .stride = sizeof(struct Vertex),
52             .inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
53         };
54     }
55 
getAttributeDescriptiongfxstream::vk::__anon5852debb0111::Vertex56     static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescription() {
57         return {
58             VkVertexInputAttributeDescription{
59                 .location = 0,
60                 .binding = 0,
61                 .format = VK_FORMAT_R32G32_SFLOAT,
62                 .offset = offsetof(struct Vertex, pos),
63             },
64             VkVertexInputAttributeDescription{
65                 .location = 1,
66                 .binding = 0,
67                 .format = VK_FORMAT_R32G32_SFLOAT,
68                 .offset = offsetof(struct Vertex, tex),
69             },
70         };
71     }
72 };
73 
74 static const std::vector<Vertex> k_vertices = {
75     // clang-format off
76     { .pos = {-1.0f, -1.0f}, .tex = {0.0f, 0.0f}},
77     { .pos = { 1.0f, -1.0f}, .tex = {1.0f, 0.0f}},
78     { .pos = { 1.0f,  1.0f}, .tex = {1.0f, 1.0f}},
79     { .pos = {-1.0f,  1.0f}, .tex = {0.0f, 1.0f}},
80     // clang-format on
81 };
82 
83 static const std::vector<uint16_t> k_indices = {0, 1, 2, 2, 3, 0};
84 
createShaderModule(const VulkanDispatch & vk,VkDevice device,const std::vector<uint32_t> & code)85 static VkShaderModule createShaderModule(const VulkanDispatch& vk, VkDevice device,
86                                          const std::vector<uint32_t>& code) {
87     const VkShaderModuleCreateInfo shaderModuleCi = {
88         .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
89         .codeSize = static_cast<uint32_t>(code.size() * sizeof(uint32_t)),
90         .pCode = code.data(),
91     };
92     VkShaderModule res;
93     VK_CHECK(vk.vkCreateShaderModule(device, &shaderModuleCi, nullptr, &res));
94     return res;
95 }
96 
97 }  // namespace
98 
RenderTarget(const VulkanDispatch & vk,VkDevice vkDevice,VkImage vkImage,VkImageView vkImageView,uint32_t width,uint32_t height,VkRenderPass vkRenderPass)99 CompositorVk::RenderTarget::RenderTarget(const VulkanDispatch& vk, VkDevice vkDevice,
100                                          VkImage vkImage, VkImageView vkImageView, uint32_t width,
101                                          uint32_t height, VkRenderPass vkRenderPass)
102     : m_vk(vk),
103       m_vkDevice(vkDevice),
104       m_vkImage(vkImage),
105       m_vkFramebuffer(VK_NULL_HANDLE),
106       m_width(width),
107       m_height(height) {
108     if (vkImageView == VK_NULL_HANDLE) {
109         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
110             << "CompositorVk found empty image view handle when creating RenderTarget.";
111     }
112 
113     const VkFramebufferCreateInfo framebufferCi = {
114         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
115         .flags = 0,
116         .renderPass = vkRenderPass,
117         .attachmentCount = 1,
118         .pAttachments = &vkImageView,
119         .width = width,
120         .height = height,
121         .layers = 1,
122     };
123     VK_CHECK(m_vk.vkCreateFramebuffer(vkDevice, &framebufferCi, nullptr, &m_vkFramebuffer));
124 }
125 
~RenderTarget()126 CompositorVk::RenderTarget::~RenderTarget() {
127     if (m_vkFramebuffer != VK_NULL_HANDLE) {
128         m_vk.vkDestroyFramebuffer(m_vkDevice, m_vkFramebuffer, nullptr);
129     }
130 }
131 
create(const VulkanDispatch & vk,VkDevice vkDevice,VkPhysicalDevice vkPhysicalDevice,VkQueue vkQueue,std::shared_ptr<android::base::Lock> queueLock,uint32_t queueFamilyIndex,uint32_t maxFramesInFlight)132 std::unique_ptr<CompositorVk> CompositorVk::create(const VulkanDispatch& vk, VkDevice vkDevice,
133                                                    VkPhysicalDevice vkPhysicalDevice,
134                                                    VkQueue vkQueue,
135                                                    std::shared_ptr<android::base::Lock> queueLock,
136                                                    uint32_t queueFamilyIndex,
137                                                    uint32_t maxFramesInFlight) {
138     auto res = std::unique_ptr<CompositorVk>(new CompositorVk(
139         vk, vkDevice, vkPhysicalDevice, vkQueue, queueLock, queueFamilyIndex, maxFramesInFlight));
140     res->setUpCommandPool();
141     res->setUpSampler();
142     res->setUpGraphicsPipeline();
143     res->setUpVertexBuffers();
144     res->setUpUniformBuffers();
145     res->setUpDescriptorSets();
146     res->setUpFences();
147     res->setUpFrameResourceFutures();
148     return res;
149 }
150 
CompositorVk(const VulkanDispatch & vk,VkDevice vkDevice,VkPhysicalDevice vkPhysicalDevice,VkQueue vkQueue,std::shared_ptr<android::base::Lock> queueLock,uint32_t queueFamilyIndex,uint32_t maxFramesInFlight)151 CompositorVk::CompositorVk(const VulkanDispatch& vk, VkDevice vkDevice,
152                            VkPhysicalDevice vkPhysicalDevice, VkQueue vkQueue,
153                            std::shared_ptr<android::base::Lock> queueLock,
154                            uint32_t queueFamilyIndex, uint32_t maxFramesInFlight)
155     : CompositorVkBase(vk, vkDevice, vkPhysicalDevice, vkQueue, queueLock, queueFamilyIndex,
156                        maxFramesInFlight),
157       m_maxFramesInFlight(maxFramesInFlight),
158       m_renderTargetCache(k_renderTargetCacheSize) {}
159 
~CompositorVk()160 CompositorVk::~CompositorVk() {
161     {
162         android::base::AutoLock lock(*m_vkQueueLock);
163         VK_CHECK(vk_util::waitForVkQueueIdleWithRetry(m_vk, m_vkQueue));
164     }
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.vkDestroySampler(m_vkDevice, m_vkSampler, nullptr);
179     m_vk.vkDestroyDescriptorSetLayout(m_vkDevice, m_vkDescriptorSetLayout, nullptr);
180     m_vk.vkDestroyCommandPool(m_vkDevice, m_vkCommandPool, nullptr);
181     for (PerFrameResources& frameResources : m_frameResources) {
182         m_vk.vkDestroyFence(m_vkDevice, frameResources.m_vkFence, nullptr);
183     }
184 }
185 
setUpGraphicsPipeline()186 void CompositorVk::setUpGraphicsPipeline() {
187     const std::vector<uint32_t> vertSpvBuff(CompositorVkShader::compositorVertexShader,
188                                             std::end(CompositorVkShader::compositorVertexShader));
189     const std::vector<uint32_t> fragSpvBuff(CompositorVkShader::compositorFragmentShader,
190                                             std::end(CompositorVkShader::compositorFragmentShader));
191     const auto vertShaderMod = createShaderModule(m_vk, m_vkDevice, vertSpvBuff);
192     const auto fragShaderMod = createShaderModule(m_vk, m_vkDevice, fragSpvBuff);
193 
194     const VkPipelineShaderStageCreateInfo shaderStageCis[2] = {
195         VkPipelineShaderStageCreateInfo{
196             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
197             .stage = VK_SHADER_STAGE_VERTEX_BIT,
198             .module = vertShaderMod,
199             .pName = "main",
200         },
201         VkPipelineShaderStageCreateInfo{
202             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
203             .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
204             .module = fragShaderMod,
205             .pName = "main",
206         },
207     };
208 
209     const auto vertexAttributeDescription = Vertex::getAttributeDescription();
210     const auto vertexBindingDescription = Vertex::getBindingDescription();
211     const VkPipelineVertexInputStateCreateInfo vertexInputStateCi = {
212         .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
213         .vertexBindingDescriptionCount = 1,
214         .pVertexBindingDescriptions = &vertexBindingDescription,
215         .vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexAttributeDescription.size()),
216         .pVertexAttributeDescriptions = vertexAttributeDescription.data(),
217     };
218     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCi = {
219         .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
220         .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
221         .primitiveRestartEnable = VK_FALSE,
222     };
223 
224     const VkPipelineViewportStateCreateInfo viewportStateCi = {
225         .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
226         .viewportCount = 1,
227         // The viewport state is dynamic.
228         .pViewports = nullptr,
229         .scissorCount = 1,
230         // The scissor state is dynamic.
231         .pScissors = nullptr,
232     };
233 
234     const VkPipelineRasterizationStateCreateInfo rasterizerStateCi = {
235         .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
236         .depthClampEnable = VK_FALSE,
237         .rasterizerDiscardEnable = VK_FALSE,
238         .polygonMode = VK_POLYGON_MODE_FILL,
239         .cullMode = VK_CULL_MODE_BACK_BIT,
240         .frontFace = VK_FRONT_FACE_CLOCKWISE,
241         .depthBiasEnable = VK_FALSE,
242         .depthBiasConstantFactor = 0.0f,
243         .depthBiasClamp = 0.0f,
244         .depthBiasSlopeFactor = 0.0f,
245         .lineWidth = 1.0f,
246     };
247 
248     const VkPipelineMultisampleStateCreateInfo multisampleStateCi = {
249         .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
250         .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
251         .sampleShadingEnable = VK_FALSE,
252         .minSampleShading = 1.0f,
253         .pSampleMask = nullptr,
254         .alphaToCoverageEnable = VK_FALSE,
255         .alphaToOneEnable = VK_FALSE,
256     };
257 
258     const VkPipelineColorBlendAttachmentState colorBlendAttachment = {
259         .blendEnable = VK_TRUE,
260         .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
261         .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
262         .colorBlendOp = VK_BLEND_OP_ADD,
263         .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
264         .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
265         .alphaBlendOp = VK_BLEND_OP_ADD,
266         .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
267                           VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
268     };
269 
270     const VkPipelineColorBlendStateCreateInfo colorBlendStateCi = {
271         .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
272         .logicOpEnable = VK_FALSE,
273         .attachmentCount = 1,
274         .pAttachments = &colorBlendAttachment,
275     };
276 
277     const VkDynamicState dynamicStates[] = {
278         VK_DYNAMIC_STATE_VIEWPORT,
279         VK_DYNAMIC_STATE_SCISSOR,
280     };
281     const VkPipelineDynamicStateCreateInfo dynamicStateCi = {
282         .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
283         .dynamicStateCount = std::size(dynamicStates),
284         .pDynamicStates = dynamicStates,
285     };
286 
287     const VkDescriptorSetLayoutBinding layoutBindings[2] = {
288         VkDescriptorSetLayoutBinding{
289             .binding = 0,
290             .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
291             .descriptorCount = 1,
292             .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
293             .pImmutableSamplers = &m_vkSampler,
294         },
295         VkDescriptorSetLayoutBinding{
296             .binding = 1,
297             .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
298             .descriptorCount = 1,
299             .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
300             .pImmutableSamplers = nullptr,
301         },
302     };
303 
304     const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCi = {
305         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
306         .pNext = nullptr,
307         .flags = 0,
308         .bindingCount = static_cast<uint32_t>(std::size(layoutBindings)),
309         .pBindings = layoutBindings,
310     };
311     VK_CHECK(m_vk.vkCreateDescriptorSetLayout(m_vkDevice, &descriptorSetLayoutCi, nullptr,
312                                               &m_vkDescriptorSetLayout));
313 
314     const VkPipelineLayoutCreateInfo pipelineLayoutCi = {
315         .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
316         .setLayoutCount = 1,
317         .pSetLayouts = &m_vkDescriptorSetLayout,
318         .pushConstantRangeCount = 0,
319     };
320 
321     VK_CHECK(
322         m_vk.vkCreatePipelineLayout(m_vkDevice, &pipelineLayoutCi, nullptr, &m_vkPipelineLayout));
323 
324     const VkAttachmentDescription colorAttachment = {
325         .format = VK_FORMAT_R8G8B8A8_UNORM,
326         .samples = VK_SAMPLE_COUNT_1_BIT,
327         .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
328         .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
329         .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
330         .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
331         .initialLayout = kTargetImageInitialLayoutUsed,
332         .finalLayout = kTargetImageFinalLayoutUsed,
333     };
334 
335     const VkAttachmentReference colorAttachmentRef = {
336         .attachment = 0,
337         .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
338     };
339 
340     const VkSubpassDescription subpass = {
341         .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
342         .colorAttachmentCount = 1,
343         .pColorAttachments = &colorAttachmentRef,
344     };
345 
346     // TODO: to support multiple layer composition, we could run the same render
347     // pass for multiple time. In that case, we should use explicit
348     // VkImageMemoryBarriers to transform the image layout instead of relying on
349     // renderpass to do it.
350     const VkSubpassDependency subpassDependency = {
351         .srcSubpass = VK_SUBPASS_EXTERNAL,
352         .dstSubpass = 0,
353         .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
354         .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
355         .srcAccessMask = 0,
356         .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
357     };
358 
359     const VkRenderPassCreateInfo renderPassCi = {
360         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
361         .attachmentCount = 1,
362         .pAttachments = &colorAttachment,
363         .subpassCount = 1,
364         .pSubpasses = &subpass,
365         .dependencyCount = 1,
366         .pDependencies = &subpassDependency,
367     };
368     VK_CHECK(m_vk.vkCreateRenderPass(m_vkDevice, &renderPassCi, nullptr, &m_vkRenderPass));
369 
370     const VkGraphicsPipelineCreateInfo graphicsPipelineCi = {
371         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
372         .stageCount = static_cast<uint32_t>(std::size(shaderStageCis)),
373         .pStages = shaderStageCis,
374         .pVertexInputState = &vertexInputStateCi,
375         .pInputAssemblyState = &inputAssemblyStateCi,
376         .pViewportState = &viewportStateCi,
377         .pRasterizationState = &rasterizerStateCi,
378         .pMultisampleState = &multisampleStateCi,
379         .pDepthStencilState = nullptr,
380         .pColorBlendState = &colorBlendStateCi,
381         .pDynamicState = &dynamicStateCi,
382         .layout = m_vkPipelineLayout,
383         .renderPass = m_vkRenderPass,
384         .subpass = 0,
385         .basePipelineHandle = VK_NULL_HANDLE,
386         .basePipelineIndex = -1,
387     };
388     VK_CHECK(m_vk.vkCreateGraphicsPipelines(m_vkDevice, VK_NULL_HANDLE, 1, &graphicsPipelineCi,
389                                             nullptr, &m_graphicsVkPipeline));
390 
391     m_vk.vkDestroyShaderModule(m_vkDevice, vertShaderMod, nullptr);
392     m_vk.vkDestroyShaderModule(m_vkDevice, fragShaderMod, nullptr);
393 }
394 
setUpVertexBuffers()395 void CompositorVk::setUpVertexBuffers() {
396     const VkDeviceSize vertexBufferSize = sizeof(Vertex) * k_vertices.size();
397     std::tie(m_vertexVkBuffer, m_vertexVkDeviceMemory) =
398         createBuffer(vertexBufferSize,
399                      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
400                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
401             .value();
402     auto [vertexStagingBuffer, vertexStagingBufferMemory] =
403         createStagingBufferWithData(k_vertices.data(), vertexBufferSize);
404     copyBuffer(vertexStagingBuffer, m_vertexVkBuffer, vertexBufferSize);
405     m_vk.vkDestroyBuffer(m_vkDevice, vertexStagingBuffer, nullptr);
406     m_vk.vkFreeMemory(m_vkDevice, vertexStagingBufferMemory, nullptr);
407 
408     VkDeviceSize indexBufferSize = sizeof(k_indices[0]) * k_indices.size();
409     auto [indexStagingBuffer, indexStagingBufferMemory] =
410         createStagingBufferWithData(k_indices.data(), indexBufferSize);
411     std::tie(m_indexVkBuffer, m_indexVkDeviceMemory) =
412         createBuffer(indexBufferSize,
413                      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
414                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
415             .value();
416 
417     copyBuffer(indexStagingBuffer, m_indexVkBuffer, indexBufferSize);
418     m_vk.vkDestroyBuffer(m_vkDevice, indexStagingBuffer, nullptr);
419     m_vk.vkFreeMemory(m_vkDevice, indexStagingBufferMemory, nullptr);
420 }
421 
setUpDescriptorSets()422 void CompositorVk::setUpDescriptorSets() {
423     const uint32_t descriptorSetsPerFrame = kMaxLayersPerFrame;
424     const uint32_t descriptorSetsTotal = descriptorSetsPerFrame * m_maxFramesInFlight;
425 
426     const uint32_t descriptorsOfEachTypePerSet = 1;
427     const uint32_t descriptorsOfEachTypePerFrame =
428         descriptorSetsPerFrame * descriptorsOfEachTypePerSet;
429     const uint32_t descriptorsOfEachTypeTotal = descriptorsOfEachTypePerFrame * m_maxFramesInFlight;
430 
431     const VkDescriptorPoolSize descriptorPoolSizes[2] = {
432         VkDescriptorPoolSize{
433             .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
434             .descriptorCount = descriptorsOfEachTypeTotal,
435         },
436         VkDescriptorPoolSize{
437             .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
438             .descriptorCount = descriptorsOfEachTypeTotal,
439         }};
440     const VkDescriptorPoolCreateInfo descriptorPoolCi = {
441         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
442         .flags = 0,
443         .maxSets = descriptorSetsTotal,
444         .poolSizeCount = static_cast<uint32_t>(std::size(descriptorPoolSizes)),
445         .pPoolSizes = descriptorPoolSizes,
446     };
447     VK_CHECK(
448         m_vk.vkCreateDescriptorPool(m_vkDevice, &descriptorPoolCi, nullptr, &m_vkDescriptorPool));
449 
450     const std::vector<VkDescriptorSetLayout> frameDescriptorSetLayouts(descriptorSetsPerFrame,
451                                                                        m_vkDescriptorSetLayout);
452     const VkDescriptorSetAllocateInfo frameDescriptorSetAllocInfo = {
453         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
454         .descriptorPool = m_vkDescriptorPool,
455         .descriptorSetCount = descriptorSetsPerFrame,
456         .pSetLayouts = frameDescriptorSetLayouts.data(),
457     };
458 
459     VkDeviceSize uniformBufferOffset = 0;
460     for (uint32_t frameIndex = 0; frameIndex < m_maxFramesInFlight; ++frameIndex) {
461         PerFrameResources& frameResources = m_frameResources[frameIndex];
462         frameResources.m_layerDescriptorSets.resize(descriptorSetsPerFrame);
463 
464         VK_CHECK(m_vk.vkAllocateDescriptorSets(m_vkDevice, &frameDescriptorSetAllocInfo,
465                                                frameResources.m_layerDescriptorSets.data()));
466 
467         for (uint32_t layerIndex = 0; layerIndex < kMaxLayersPerFrame; ++layerIndex) {
468             const VkDescriptorBufferInfo bufferInfo = {
469                 .buffer = m_uniformStorage.m_vkBuffer,
470                 .offset = uniformBufferOffset,
471                 .range = sizeof(UniformBufferBinding),
472             };
473             const VkWriteDescriptorSet descriptorSetWrite = {
474                 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
475                 .dstSet = frameResources.m_layerDescriptorSets[layerIndex],
476                 .dstBinding = 1,
477                 .dstArrayElement = 0,
478                 .descriptorCount = 1,
479                 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
480                 .pBufferInfo = &bufferInfo,
481             };
482             m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0, nullptr);
483 
484             uniformBufferOffset += m_uniformStorage.m_stride;
485         }
486     }
487 }
488 
setUpCommandPool()489 void CompositorVk::setUpCommandPool() {
490     const VkCommandPoolCreateInfo commandPoolCreateInfo = {
491         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
492         .flags = 0,
493         .queueFamilyIndex = m_queueFamilyIndex,
494     };
495 
496     VkCommandPool commandPool = VK_NULL_HANDLE;
497     VK_CHECK(m_vk.vkCreateCommandPool(m_vkDevice, &commandPoolCreateInfo, nullptr, &commandPool));
498     m_vkCommandPool = commandPool;
499 }
500 
setUpFences()501 void CompositorVk::setUpFences() {
502     for (uint32_t frameIndex = 0; frameIndex < m_maxFramesInFlight; ++frameIndex) {
503         PerFrameResources& frameResources = m_frameResources[frameIndex];
504 
505         const VkFenceCreateInfo fenceCi = {
506             .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
507         };
508 
509         VkFence fence;
510         VK_CHECK(m_vk.vkCreateFence(m_vkDevice, &fenceCi, nullptr, &fence));
511 
512         frameResources.m_vkFence = fence;
513     }
514 }
515 
setUpFrameResourceFutures()516 void CompositorVk::setUpFrameResourceFutures() {
517     for (uint32_t frameIndex = 0; frameIndex < m_maxFramesInFlight; ++frameIndex) {
518         std::shared_future<PerFrameResources*> availableFrameResourceFuture =
519             std::async(std::launch::deferred, [this, frameIndex] {
520                 return &m_frameResources[frameIndex];
521             }).share();
522 
523         m_availableFrameResources.push_back(std::move(availableFrameResourceFuture));
524     }
525 }
526 
setUpUniformBuffers()527 void CompositorVk::setUpUniformBuffers() {
528     VkPhysicalDeviceProperties physicalDeviceProperties;
529     m_vk.vkGetPhysicalDeviceProperties(m_vkPhysicalDevice, &physicalDeviceProperties);
530     const VkDeviceSize alignment = physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
531     m_uniformStorage.m_stride = ((sizeof(UniformBufferBinding) - 1) / alignment + 1) * alignment;
532 
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 
549     void* mapped = nullptr;
550     VK_CHECK(m_vk.vkMapMemory(m_vkDevice, m_uniformStorage.m_vkDeviceMemory, 0, size, 0, &mapped));
551 
552     uint8_t* data = reinterpret_cast<uint8_t*>(mapped);
553     for (uint32_t frameIndex = 0; frameIndex < m_maxFramesInFlight; ++frameIndex) {
554         PerFrameResources& frameResources = m_frameResources[frameIndex];
555         for (uint32_t layerIndex = 0; layerIndex < kMaxLayersPerFrame; ++layerIndex) {
556             auto* layerUboStorage = reinterpret_cast<UniformBufferBinding*>(data);
557             frameResources.m_layerUboStorages.push_back(layerUboStorage);
558             data += m_uniformStorage.m_stride;
559         }
560     }
561 }
562 
setUpSampler()563 void CompositorVk::setUpSampler() {
564     // The texture coordinate transformation matrices for flip/rotate/etc
565     // currently depends on this being repeat.
566     constexpr const VkSamplerAddressMode kSamplerMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
567 
568     const VkSamplerCreateInfo samplerCi = {
569         .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
570         .magFilter = VK_FILTER_LINEAR,
571         .minFilter = VK_FILTER_LINEAR,
572         .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
573         .addressModeU = kSamplerMode,
574         .addressModeV = kSamplerMode,
575         .addressModeW = kSamplerMode,
576         .mipLodBias = 0.0f,
577         .anisotropyEnable = VK_FALSE,
578         .maxAnisotropy = 1.0f,
579         .compareEnable = VK_FALSE,
580         .compareOp = VK_COMPARE_OP_ALWAYS,
581         .minLod = 0.0f,
582         .maxLod = 0.0f,
583         .borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
584         .unnormalizedCoordinates = VK_FALSE,
585     };
586     VK_CHECK(m_vk.vkCreateSampler(m_vkDevice, &samplerCi, nullptr, &m_vkSampler));
587 }
588 
589 // Create a VkBuffer and a bound VkDeviceMemory. When the specified memory type
590 // can't be found, return std::nullopt. When Vulkan call fails, terminate the
591 // program.
createBuffer(VkDeviceSize size,VkBufferUsageFlags usage,VkMemoryPropertyFlags memProperty) const592 std::optional<std::tuple<VkBuffer, VkDeviceMemory>> CompositorVk::createBuffer(
593     VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memProperty) const {
594     const VkBufferCreateInfo bufferCi = {
595         .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
596         .size = size,
597         .usage = usage,
598         .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
599     };
600     VkBuffer resBuffer;
601     VK_CHECK(m_vk.vkCreateBuffer(m_vkDevice, &bufferCi, nullptr, &resBuffer));
602     VkMemoryRequirements memRequirements;
603     m_vk.vkGetBufferMemoryRequirements(m_vkDevice, resBuffer, &memRequirements);
604     VkPhysicalDeviceMemoryProperties physicalMemProperties;
605     m_vk.vkGetPhysicalDeviceMemoryProperties(m_vkPhysicalDevice, &physicalMemProperties);
606     auto maybeMemoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, memProperty);
607     if (!maybeMemoryTypeIndex.has_value()) {
608         ERR("Failed to find memory type for creating buffer.");
609         m_vk.vkDestroyBuffer(m_vkDevice, resBuffer, nullptr);
610         return std::nullopt;
611     }
612     const VkMemoryAllocateInfo memAllocInfo = {
613         .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
614         .allocationSize = memRequirements.size,
615         .memoryTypeIndex = maybeMemoryTypeIndex.value(),
616     };
617     VkDeviceMemory resMemory;
618     VK_CHECK_MEMALLOC(m_vk.vkAllocateMemory(m_vkDevice, &memAllocInfo, nullptr, &resMemory),
619                     memAllocInfo);
620     VK_CHECK(m_vk.vkBindBufferMemory(m_vkDevice, resBuffer, resMemory, 0));
621     return std::make_tuple(resBuffer, resMemory);
622 }
623 
createStagingBufferWithData(const void * srcData,VkDeviceSize size) const624 std::tuple<VkBuffer, VkDeviceMemory> CompositorVk::createStagingBufferWithData(
625     const void* srcData, VkDeviceSize size) const {
626     auto [stagingBuffer, stagingBufferMemory] =
627         createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
628                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
629             .value();
630     void* data;
631     VK_CHECK(m_vk.vkMapMemory(m_vkDevice, stagingBufferMemory, 0, size, 0, &data));
632     memcpy(data, srcData, size);
633     m_vk.vkUnmapMemory(m_vkDevice, stagingBufferMemory);
634     return std::make_tuple(stagingBuffer, stagingBufferMemory);
635 }
636 
copyBuffer(VkBuffer src,VkBuffer dst,VkDeviceSize size) const637 void CompositorVk::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) const {
638     runSingleTimeCommands(m_vkQueue, m_vkQueueLock, [&, this](const auto& cmdBuff) {
639         VkBufferCopy copyRegion = {};
640         copyRegion.srcOffset = 0;
641         copyRegion.dstOffset = 0;
642         copyRegion.size = size;
643         m_vk.vkCmdCopyBuffer(cmdBuff, src, dst, 1, &copyRegion);
644     });
645 }
646 
647 // TODO: move this to another common CRTP helper class in vk_util.h.
getFormatFeatures(VkFormat format,VkImageTiling tiling)648 VkFormatFeatureFlags CompositorVk::getFormatFeatures(VkFormat format, VkImageTiling tiling) {
649     auto i = m_vkFormatProperties.find(format);
650     if (i == m_vkFormatProperties.end()) {
651         VkFormatProperties formatProperties;
652         m_vk.vkGetPhysicalDeviceFormatProperties(m_vkPhysicalDevice, format, &formatProperties);
653         i = m_vkFormatProperties.emplace(format, formatProperties).first;
654     }
655     const VkFormatProperties& formatProperties = i->second;
656     VkFormatFeatureFlags formatFeatures = 0;
657     if (tiling == VK_IMAGE_TILING_LINEAR) {
658         formatFeatures = formatProperties.linearTilingFeatures;
659     } else if (tiling == VK_IMAGE_TILING_OPTIMAL) {
660         formatFeatures = formatProperties.optimalTilingFeatures;
661     } else {
662         ERR("Unknown tiling:%#" PRIx64 ".", static_cast<uint64_t>(tiling));
663     }
664     return formatFeatures;
665 }
666 
getOrCreateRenderTargetInfo(const BorrowedImageInfoVk & imageInfo)667 CompositorVk::RenderTarget* CompositorVk::getOrCreateRenderTargetInfo(
668     const BorrowedImageInfoVk& imageInfo) {
669     auto* renderTargetPtr = m_renderTargetCache.get(imageInfo.id);
670     if (renderTargetPtr != nullptr) {
671         return renderTargetPtr->get();
672     }
673 
674     auto* renderTarget = new RenderTarget(m_vk, m_vkDevice, imageInfo.image, imageInfo.imageView,
675                                           imageInfo.imageCreateInfo.extent.width,
676                                           imageInfo.imageCreateInfo.extent.height, m_vkRenderPass);
677 
678     m_renderTargetCache.set(imageInfo.id, std::unique_ptr<RenderTarget>(renderTarget));
679 
680     return renderTarget;
681 }
682 
canCompositeFrom(const VkImageCreateInfo & imageCi)683 bool CompositorVk::canCompositeFrom(const VkImageCreateInfo& imageCi) {
684     VkFormatFeatureFlags formatFeatures = getFormatFeatures(imageCi.format, imageCi.tiling);
685     if (!(formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
686         ERR("The format, %s, with tiling, %s, doesn't support the "
687             "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT feature. All supported features are %s.",
688             string_VkFormat(imageCi.format), string_VkImageTiling(imageCi.tiling),
689             string_VkFormatFeatureFlags(formatFeatures).c_str());
690         return false;
691     }
692     return true;
693 }
694 
canCompositeTo(const VkImageCreateInfo & imageCi)695 bool CompositorVk::canCompositeTo(const VkImageCreateInfo& imageCi) {
696     VkFormatFeatureFlags formatFeatures = getFormatFeatures(imageCi.format, imageCi.tiling);
697     if (!(formatFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
698         ERR("The format, %s, with tiling, %s, doesn't support the "
699             "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT feature. All supported features are %s.",
700             string_VkFormat(imageCi.format), string_VkImageTiling(imageCi.tiling),
701             string_VkFormatFeatureFlags(formatFeatures).c_str());
702         return false;
703     }
704     if (!(imageCi.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
705         ERR("The VkImage is not created with the VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT usage flag. "
706             "The usage flags are %s.",
707             string_VkImageUsageFlags(imageCi.usage).c_str());
708         return false;
709     }
710     if (imageCi.format != k_renderTargetFormat) {
711         ERR("The format of the image, %s, is not supported by the CompositorVk as the render "
712             "target.",
713             string_VkFormat(imageCi.format));
714         return false;
715     }
716     return true;
717 }
718 
buildCompositionVk(const CompositionRequest & compositionRequest,CompositionVk * compositionVk)719 void CompositorVk::buildCompositionVk(const CompositionRequest& compositionRequest,
720                                       CompositionVk* compositionVk) {
721     const BorrowedImageInfoVk* targetImage = getInfoOrAbort(compositionRequest.target);
722     RenderTarget* targetImageRenderTarget = getOrCreateRenderTargetInfo(*targetImage);
723 
724     const uint32_t targetWidth = targetImage->width;
725     const uint32_t targetHeight = targetImage->height;
726 
727     compositionVk->targetImage = targetImage;
728     compositionVk->targetFramebuffer = targetImageRenderTarget->m_vkFramebuffer;
729 
730     for (const CompositionRequestLayer& layer : compositionRequest.layers) {
731         const BorrowedImageInfoVk* sourceImage = getInfoOrAbort(layer.source);
732         if (!canCompositeFrom(sourceImage->imageCreateInfo)) {
733             continue;
734         }
735 
736         const uint32_t sourceImageWidth = sourceImage->width;
737         const uint32_t sourceImageHeight = sourceImage->height;
738 
739         // Calculate the posTransform and the texcoordTransform needed in the
740         // uniform of the Compositor.vert shader. The posTransform should transform
741         // the square(top = -1, bottom = 1, left = -1, right = 1) to the position
742         // where the layer should be drawn in NDC space given the layer.
743         // texcoordTransform should transform the unit square(top = 0, bottom = 1,
744         // left = 0, right = 1) to where we should sample the layer in the
745         // normalized uv space given the composeLayer.
746         const hwc_rect_t& posRect = layer.props.displayFrame;
747         const hwc_frect_t& texcoordRect = layer.props.crop;
748 
749         const int posWidth = posRect.right - posRect.left;
750         const int posHeight = posRect.bottom - posRect.top;
751 
752         const float posScaleX = float(posWidth) / targetWidth;
753         const float posScaleY = float(posHeight) / targetHeight;
754 
755         const float posTranslateX = -1.0f + posScaleX + 2.0f * float(posRect.left) / targetWidth;
756         const float posTranslateY = -1.0f + posScaleY + 2.0f * float(posRect.top) / targetHeight;
757 
758         float texCoordScaleX = (texcoordRect.right - texcoordRect.left) / float(sourceImageWidth);
759         float texCoordScaleY = (texcoordRect.bottom - texcoordRect.top) / float(sourceImageHeight);
760 
761         const float texCoordTranslateX = texcoordRect.left / float(sourceImageWidth);
762         const float texCoordTranslateY = texcoordRect.top / float(sourceImageHeight);
763 
764         float texcoordRotation = 0.0f;
765 
766         const float pi = glm::pi<float>();
767 
768         switch (layer.props.transform) {
769             case HWC_TRANSFORM_NONE:
770                 break;
771             case HWC_TRANSFORM_ROT_90:
772                 texcoordRotation = pi * 0.5f;
773                 break;
774             case HWC_TRANSFORM_ROT_180:
775                 texcoordRotation = pi;
776                 break;
777             case HWC_TRANSFORM_ROT_270:
778                 texcoordRotation = pi * 1.5f;
779                 break;
780             case HWC_TRANSFORM_FLIP_H:
781                 texCoordScaleX *= -1.0f;
782                 break;
783             case HWC_TRANSFORM_FLIP_V:
784                 texCoordScaleY *= -1.0f;
785                 break;
786             case HWC_TRANSFORM_FLIP_H_ROT_90:
787                 texcoordRotation = pi * 0.5f;
788                 texCoordScaleX *= -1.0f;
789                 break;
790             case HWC_TRANSFORM_FLIP_V_ROT_90:
791                 texcoordRotation = pi * 0.5f;
792                 texCoordScaleY *= -1.0f;
793                 break;
794             default:
795                 ERR("Unknown transform:%d", static_cast<int>(layer.props.transform));
796                 break;
797         }
798 
799         const DescriptorSetContents descriptorSetContents = {
800             .binding0 =
801                 {
802                     .sampledImageView = sourceImage->imageView,
803                 },
804             .binding1 = {
805                 .positionTransform =
806                     glm::translate(glm::mat4(1.0f), glm::vec3(posTranslateX, posTranslateY, 0.0f)) *
807                     glm::scale(glm::mat4(1.0f), glm::vec3(posScaleX, posScaleY, 1.0f)),
808                 .texCoordTransform =
809                     glm::translate(glm::mat4(1.0f),
810                                    glm::vec3(texCoordTranslateX, texCoordTranslateY, 0.0f)) *
811                     glm::scale(glm::mat4(1.0f), glm::vec3(texCoordScaleX, texCoordScaleY, 1.0f)) *
812                     glm::rotate(glm::mat4(1.0f), texcoordRotation, glm::vec3(0.0f, 0.0f, 1.0f)),
813             }};
814         compositionVk->layersDescriptorSets.descriptorSets.emplace_back(descriptorSetContents);
815         compositionVk->layersSourceImages.emplace_back(sourceImage);
816     }
817 }
818 
compose(const CompositionRequest & compositionRequest)819 CompositorVk::CompositionFinishedWaitable CompositorVk::compose(
820     const CompositionRequest& compositionRequest) {
821     CompositionVk compositionVk;
822     buildCompositionVk(compositionRequest, &compositionVk);
823 
824     // Grab and wait for the next available resources.
825     if (m_availableFrameResources.empty()) {
826         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
827             << "CompositorVk failed to get PerFrameResources.";
828     }
829     auto frameResourceFuture = std::move(m_availableFrameResources.front());
830     m_availableFrameResources.pop_front();
831     PerFrameResources* frameResources = frameResourceFuture.get();
832 
833     updateDescriptorSetsIfChanged(compositionVk.layersDescriptorSets, frameResources);
834 
835     std::vector<VkImageMemoryBarrier> preCompositionQueueTransferBarriers;
836     std::vector<VkImageMemoryBarrier> preCompositionLayoutTransitionBarriers;
837     std::vector<VkImageMemoryBarrier> postCompositionLayoutTransitionBarriers;
838     std::vector<VkImageMemoryBarrier> postCompositionQueueTransferBarriers;
839     addNeededBarriersToUseBorrowedImage(
840         *compositionVk.targetImage, m_queueFamilyIndex, kTargetImageInitialLayoutUsed,
841         kTargetImageFinalLayoutUsed, VK_ACCESS_MEMORY_WRITE_BIT,
842         &preCompositionQueueTransferBarriers, &preCompositionLayoutTransitionBarriers,
843         &postCompositionLayoutTransitionBarriers, &postCompositionQueueTransferBarriers);
844     for (const BorrowedImageInfoVk* sourceImage : compositionVk.layersSourceImages) {
845         addNeededBarriersToUseBorrowedImage(
846             *sourceImage, m_queueFamilyIndex, kSourceImageInitialLayoutUsed,
847             kSourceImageFinalLayoutUsed, VK_ACCESS_SHADER_READ_BIT,
848             &preCompositionQueueTransferBarriers, &preCompositionLayoutTransitionBarriers,
849             &postCompositionLayoutTransitionBarriers, &postCompositionQueueTransferBarriers);
850     }
851 
852     VkCommandBuffer& commandBuffer = frameResources->m_vkCommandBuffer;
853     if (commandBuffer != VK_NULL_HANDLE) {
854         m_vk.vkFreeCommandBuffers(m_vkDevice, m_vkCommandPool, 1, &commandBuffer);
855     }
856 
857     const VkCommandBufferAllocateInfo commandBufferAllocInfo = {
858         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
859         .commandPool = m_vkCommandPool,
860         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
861         .commandBufferCount = 1,
862     };
863     VK_CHECK(m_vk.vkAllocateCommandBuffers(m_vkDevice, &commandBufferAllocInfo, &commandBuffer));
864 
865     const VkCommandBufferBeginInfo beginInfo = {
866         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
867         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
868     };
869     VK_CHECK(m_vk.vkBeginCommandBuffer(commandBuffer, &beginInfo));
870 
871     if (!preCompositionQueueTransferBarriers.empty()) {
872         m_vk.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
873                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr,
874                                   static_cast<uint32_t>(preCompositionQueueTransferBarriers.size()),
875                                   preCompositionQueueTransferBarriers.data());
876     }
877     if (!preCompositionLayoutTransitionBarriers.empty()) {
878         m_vk.vkCmdPipelineBarrier(
879             commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
880             0, 0, nullptr, 0, nullptr,
881             static_cast<uint32_t>(preCompositionLayoutTransitionBarriers.size()),
882             preCompositionLayoutTransitionBarriers.data());
883     }
884 
885     const VkClearValue renderTargetClearColor = {
886         .color =
887             {
888                 .float32 = {0.0f, 0.0f, 0.0f, 1.0f},
889             },
890     };
891     const VkRenderPassBeginInfo renderPassBeginInfo = {
892         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
893         .renderPass = m_vkRenderPass,
894         .framebuffer = compositionVk.targetFramebuffer,
895         .renderArea =
896             {
897                 .offset =
898                     {
899                         .x = 0,
900                         .y = 0,
901                     },
902                 .extent =
903                     {
904                         .width = compositionVk.targetImage->imageCreateInfo.extent.width,
905                         .height = compositionVk.targetImage->imageCreateInfo.extent.height,
906                     },
907             },
908         .clearValueCount = 1,
909         .pClearValues = &renderTargetClearColor,
910     };
911     m_vk.vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
912 
913     m_vk.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsVkPipeline);
914 
915     const VkRect2D scissor = {
916         .offset =
917             {
918                 .x = 0,
919                 .y = 0,
920             },
921         .extent =
922             {
923                 .width = compositionVk.targetImage->imageCreateInfo.extent.width,
924                 .height = compositionVk.targetImage->imageCreateInfo.extent.height,
925             },
926     };
927     m_vk.vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
928 
929     const VkViewport viewport = {
930         .x = 0.0f,
931         .y = 0.0f,
932         .width = static_cast<float>(compositionVk.targetImage->imageCreateInfo.extent.width),
933         .height = static_cast<float>(compositionVk.targetImage->imageCreateInfo.extent.height),
934         .minDepth = 0.0f,
935         .maxDepth = 1.0f,
936     };
937     m_vk.vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
938 
939     const VkDeviceSize offsets[] = {0};
940     m_vk.vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_vertexVkBuffer, offsets);
941 
942     m_vk.vkCmdBindIndexBuffer(commandBuffer, m_indexVkBuffer, 0, VK_INDEX_TYPE_UINT16);
943 
944     for (int layerIndex = 0; layerIndex < compositionVk.layersSourceImages.size(); ++layerIndex) {
945         VkDescriptorSet layerDescriptorSet = frameResources->m_layerDescriptorSets[layerIndex];
946 
947         m_vk.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
948                                      m_vkPipelineLayout,
949                                      /*firstSet=*/0,
950                                      /*descriptorSetCount=*/1, &layerDescriptorSet,
951                                      /*dynamicOffsetCount=*/0,
952                                      /*pDynamicOffsets=*/nullptr);
953 
954         m_vk.vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(k_indices.size()), 1, 0, 0, 0);
955     }
956 
957     m_vk.vkCmdEndRenderPass(commandBuffer);
958 
959     // Insert a VkImageMemoryBarrier so that the vkCmdBlitImage in post will wait for the rendering
960     // to the render target to complete.
961     const VkImageMemoryBarrier renderTargetBarrier = {
962         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
963         .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
964         .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
965         .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
966         .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
967         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
968         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
969         .image = compositionVk.targetImage->image,
970         .subresourceRange =
971             {
972                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
973                 .baseMipLevel = 0,
974                 .levelCount = 1,
975                 .baseArrayLayer = 0,
976                 .layerCount = 1,
977             },
978     };
979     m_vk.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
980                               VK_PIPELINE_STAGE_TRANSFER_BIT,
981                               /*dependencyFlags=*/0,
982                               /*memoryBarrierCount=*/0,
983                               /*pMemoryBarriers=*/nullptr,
984                               /*bufferMemoryBarrierCount=*/0,
985                               /*pBufferMemoryBarriers=*/nullptr, 1, &renderTargetBarrier);
986 
987     if (!postCompositionLayoutTransitionBarriers.empty()) {
988         m_vk.vkCmdPipelineBarrier(
989             commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
990             0, 0, nullptr, 0, nullptr,
991             static_cast<uint32_t>(postCompositionLayoutTransitionBarriers.size()),
992             postCompositionLayoutTransitionBarriers.data());
993     }
994     if (!postCompositionQueueTransferBarriers.empty()) {
995         m_vk.vkCmdPipelineBarrier(
996             commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
997             0, 0, nullptr, 0, nullptr,
998             static_cast<uint32_t>(postCompositionQueueTransferBarriers.size()),
999             postCompositionQueueTransferBarriers.data());
1000     }
1001 
1002     VK_CHECK(m_vk.vkEndCommandBuffer(commandBuffer));
1003 
1004     VkFence composeCompleteFence = frameResources->m_vkFence;
1005     VK_CHECK(m_vk.vkResetFences(m_vkDevice, 1, &composeCompleteFence));
1006 
1007     const VkPipelineStageFlags submitWaitStages[] = {
1008         VK_PIPELINE_STAGE_TRANSFER_BIT,
1009     };
1010     const VkSubmitInfo submitInfo = {
1011         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1012         .waitSemaphoreCount = 0,
1013         .pWaitSemaphores = nullptr,
1014         .pWaitDstStageMask = submitWaitStages,
1015         .commandBufferCount = 1,
1016         .pCommandBuffers = &commandBuffer,
1017         .signalSemaphoreCount = 0,
1018         .pSignalSemaphores = nullptr,
1019     };
1020 
1021     {
1022         android::base::AutoLock lock(*m_vkQueueLock);
1023         VK_CHECK(m_vk.vkQueueSubmit(m_vkQueue, 1, &submitInfo, composeCompleteFence));
1024     }
1025 
1026     // Create a future that will return the PerFrameResources to the next
1027     // iteration of CompostiorVk::compose() once this current composition
1028     // completes.
1029     std::shared_future<PerFrameResources*> composeCompleteFutureForResources =
1030         std::async(std::launch::deferred, [composeCompleteFence, frameResources, this]() mutable {
1031             VkResult res = m_vk.vkWaitForFences(m_vkDevice, 1, &composeCompleteFence, VK_TRUE,
1032                                                 kVkWaitForFencesTimeoutNsecs);
1033             if (res == VK_SUCCESS) {
1034                 return frameResources;
1035             }
1036             if (res == VK_TIMEOUT) {
1037                 // Retry. If device lost, hopefully this returns immediately.
1038                 res = m_vk.vkWaitForFences(m_vkDevice, 1, &composeCompleteFence, VK_TRUE,
1039                                            kVkWaitForFencesTimeoutNsecs);
1040             }
1041             VK_CHECK(res);
1042             return frameResources;
1043         }).share();
1044     m_availableFrameResources.push_back(composeCompleteFutureForResources);
1045 
1046     // Create a future that will return once this current composition
1047     // completes that can be shared outside of CompositorVk.
1048     std::shared_future<void> composeCompleteFuture =
1049         std::async(std::launch::deferred, [composeCompleteFutureForResources]() {
1050             composeCompleteFutureForResources.get();
1051         }).share();
1052 
1053     return composeCompleteFuture;
1054 }
1055 
onImageDestroyed(uint32_t imageId)1056 void CompositorVk::onImageDestroyed(uint32_t imageId) { m_renderTargetCache.remove(imageId); }
1057 
operator ==(const CompositorVkBase::DescriptorSetContents & lhs,const CompositorVkBase::DescriptorSetContents & rhs)1058 bool operator==(const CompositorVkBase::DescriptorSetContents& lhs,
1059                 const CompositorVkBase::DescriptorSetContents& rhs) {
1060     return std::tie(lhs.binding0.sampledImageView, lhs.binding1.positionTransform,
1061                     lhs.binding1.texCoordTransform) == std::tie(rhs.binding0.sampledImageView,
1062                                                                 rhs.binding1.positionTransform,
1063                                                                 rhs.binding1.texCoordTransform);
1064 }
1065 
operator ==(const CompositorVkBase::FrameDescriptorSetsContents & lhs,const CompositorVkBase::FrameDescriptorSetsContents & rhs)1066 bool operator==(const CompositorVkBase::FrameDescriptorSetsContents& lhs,
1067                 const CompositorVkBase::FrameDescriptorSetsContents& rhs) {
1068     return lhs.descriptorSets == rhs.descriptorSets;
1069 }
1070 
updateDescriptorSetsIfChanged(const FrameDescriptorSetsContents & descriptorSetsContents,PerFrameResources * frameResources)1071 void CompositorVk::updateDescriptorSetsIfChanged(
1072     const FrameDescriptorSetsContents& descriptorSetsContents, PerFrameResources* frameResources) {
1073     if (frameResources->m_vkDescriptorSetsContents == descriptorSetsContents) {
1074         return;
1075     }
1076 
1077     const uint32_t numRequestedLayers =
1078         static_cast<uint32_t>(descriptorSetsContents.descriptorSets.size());
1079     if (numRequestedLayers > kMaxLayersPerFrame) {
1080         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1081             << "CompositorVk can't compose more than " << kMaxLayersPerFrame
1082             << " layers. layers asked: " << numRequestedLayers;
1083         return;
1084     }
1085 
1086     std::vector<VkDescriptorImageInfo> descriptorImageInfos(numRequestedLayers);
1087     std::vector<VkWriteDescriptorSet> descriptorWrites;
1088     for (uint32_t layerIndex = 0; layerIndex < numRequestedLayers; ++layerIndex) {
1089         const DescriptorSetContents& layerDescriptorSetContents =
1090             descriptorSetsContents.descriptorSets[layerIndex];
1091 
1092         descriptorImageInfos[layerIndex] = VkDescriptorImageInfo{
1093             // Empty as we only use immutable samplers.
1094             .sampler = VK_NULL_HANDLE,
1095             .imageView = layerDescriptorSetContents.binding0.sampledImageView,
1096             .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1097         };
1098 
1099         descriptorWrites.emplace_back(VkWriteDescriptorSet{
1100             .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1101             .dstSet = frameResources->m_layerDescriptorSets[layerIndex],
1102             .dstBinding = 0,
1103             .dstArrayElement = 0,
1104             .descriptorCount = 1,
1105             .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1106             .pImageInfo = &descriptorImageInfos[layerIndex],
1107         });
1108 
1109         UniformBufferBinding* layerUboStorage = frameResources->m_layerUboStorages[layerIndex];
1110         *layerUboStorage = layerDescriptorSetContents.binding1;
1111     }
1112 
1113     m_vk.vkUpdateDescriptorSets(m_vkDevice, descriptorWrites.size(), descriptorWrites.data(), 0,
1114                                 nullptr);
1115 
1116     frameResources->m_vkDescriptorSetsContents = descriptorSetsContents;
1117 }
1118 
1119 }  // namespace vk
1120 }  // namespace gfxstream
1121