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