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, ©Region);
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