• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "DisplayVk.h"
2 
3 #include <glm/glm.hpp>
4 #include <glm/gtx/matrix_transform_2d.hpp>
5 
6 #include "ErrorLog.h"
7 
DisplayVk(const goldfish_vk::VulkanDispatch & vk,VkPhysicalDevice vkPhysicalDevice,uint32_t swapChainQueueFamilyIndex,uint32_t compositorQueueFamilyIndex,VkDevice vkDevice,VkQueue compositorVkQueue,VkQueue swapChainVkqueue)8 DisplayVk::DisplayVk(const goldfish_vk::VulkanDispatch &vk,
9                      VkPhysicalDevice vkPhysicalDevice,
10                      uint32_t swapChainQueueFamilyIndex,
11                      uint32_t compositorQueueFamilyIndex, VkDevice vkDevice,
12                      VkQueue compositorVkQueue, VkQueue swapChainVkqueue)
13     : m_vk(vk),
14       m_vkPhysicalDevice(vkPhysicalDevice),
15       m_swapChainQueueFamilyIndex(swapChainQueueFamilyIndex),
16       m_compositorQueueFamilyIndex(compositorQueueFamilyIndex),
17       m_vkDevice(vkDevice),
18       m_compositorVkQueue(compositorVkQueue),
19       m_swapChainVkQueue(swapChainVkqueue),
20       m_vkCommandPool(VK_NULL_HANDLE),
21       m_swapChainStateVk(nullptr),
22       m_compositorVk(nullptr),
23       m_surfaceState(nullptr),
24       m_canComposite() {
25     // TODO(kaiyili): validate the capabilites of the passed in Vulkan
26     // components.
27     VkCommandPoolCreateInfo commandPoolCi = {
28         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
29         .queueFamilyIndex = m_compositorQueueFamilyIndex,
30     };
31     VK_CHECK(m_vk.vkCreateCommandPool(m_vkDevice, &commandPoolCi, nullptr,
32                                       &m_vkCommandPool));
33     VkFenceCreateInfo fenceCi = {.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
34                                  .flags = VK_FENCE_CREATE_SIGNALED_BIT};
35     VK_CHECK(m_vk.vkCreateFence(m_vkDevice, &fenceCi, nullptr,
36                                 &m_frameDrawCompleteFence));
37     VkSemaphoreCreateInfo semaphoreCi = {
38         .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
39     VK_CHECK(m_vk.vkCreateSemaphore(m_vkDevice, &semaphoreCi, nullptr,
40                                     &m_imageReadySem));
41     VK_CHECK(m_vk.vkCreateSemaphore(m_vkDevice, &semaphoreCi, nullptr,
42                                     &m_frameDrawCompleteSem));
43 
44     VkSamplerCreateInfo samplerCi = {
45         .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
46         .magFilter = VK_FILTER_NEAREST,
47         .minFilter = VK_FILTER_NEAREST,
48         .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
49         .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
50         .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
51         .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
52         .mipLodBias = 0.0f,
53         .anisotropyEnable = VK_FALSE,
54         .maxAnisotropy = 1.0f,
55         .compareEnable = VK_FALSE,
56         .compareOp = VK_COMPARE_OP_ALWAYS,
57         .minLod = 0.0f,
58         .maxLod = 0.0f,
59         .borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
60         .unnormalizedCoordinates = VK_FALSE};
61     VK_CHECK(m_vk.vkCreateSampler(m_vkDevice, &samplerCi, nullptr,
62                                   &m_compositionVkSampler));
63 }
64 
~DisplayVk()65 DisplayVk::~DisplayVk() {
66     m_vk.vkDestroySampler(m_vkDevice, m_compositionVkSampler, nullptr);
67     m_vk.vkDestroySemaphore(m_vkDevice, m_imageReadySem, nullptr);
68     m_vk.vkDestroySemaphore(m_vkDevice, m_frameDrawCompleteSem, nullptr);
69     m_vk.vkDestroyFence(m_vkDevice, m_frameDrawCompleteFence, nullptr);
70     m_compositorVk.reset();
71     m_swapChainStateVk.reset();
72     m_vk.vkDestroyCommandPool(m_vkDevice, m_vkCommandPool, nullptr);
73 }
74 
bindToSurface(VkSurfaceKHR surface,uint32_t width,uint32_t height)75 void DisplayVk::bindToSurface(VkSurfaceKHR surface, uint32_t width,
76                               uint32_t height) {
77     if (!SwapChainStateVk::validateQueueFamilyProperties(
78             m_vk, m_vkPhysicalDevice, surface, m_swapChainQueueFamilyIndex)) {
79         ERR("%s(%s:%d): DisplayVk can't create VkSwapchainKHR with given "
80             "VkDevice and VkSurfaceKHR.\n",
81             __FUNCTION__, __FILE__, static_cast<int>(__LINE__));
82         ::abort();
83     }
84     auto swapChainCi = SwapChainStateVk::createSwapChainCi(
85         m_vk, surface, m_vkPhysicalDevice, width, height,
86         {m_swapChainQueueFamilyIndex, m_compositorQueueFamilyIndex});
87     VkFormatProperties formatProps;
88     m_vk.vkGetPhysicalDeviceFormatProperties(
89         m_vkPhysicalDevice, swapChainCi->imageFormat, &formatProps);
90     if (!(formatProps.optimalTilingFeatures &
91           VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
92         ERR("%s(%s:%d): DisplayVk: The image format chosen for present VkImage "
93             "can't be used as the color attachment, and therefore can't be "
94             "used as the render target of CompositorVk.\n",
95             __FUNCTION__, __FILE__, static_cast<int>(__LINE__));
96         ::abort();
97     }
98     m_swapChainStateVk =
99         std::make_unique<SwapChainStateVk>(m_vk, m_vkDevice, *swapChainCi);
100     m_compositorVk = CompositorVk::create(
101         m_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
102         m_swapChainStateVk->getFormat(), VK_IMAGE_LAYOUT_UNDEFINED,
103         VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, width, height,
104         m_swapChainStateVk->getVkImageViews(), m_vkCommandPool);
105     auto surfaceState = std::make_unique<SurfaceState>();
106     surfaceState->m_height = height;
107     surfaceState->m_width = width;
108     m_surfaceState = std::move(surfaceState);
109 }
110 
createDisplayBuffer(VkImage image,VkFormat format,uint32_t width,uint32_t height)111 std::shared_ptr<DisplayVk::DisplayBufferInfo> DisplayVk::createDisplayBuffer(
112     VkImage image, VkFormat format, uint32_t width, uint32_t height) {
113     return std::shared_ptr<DisplayBufferInfo>(
114         new DisplayBufferInfo(m_vk, m_vkDevice, width, height, format, image));
115 }
116 
post(const std::shared_ptr<DisplayBufferInfo> & displayBufferPtr)117 void DisplayVk::post(
118     const std::shared_ptr<DisplayBufferInfo> &displayBufferPtr) {
119     if (!displayBufferPtr) {
120         fprintf(stderr, "%s: warning: null ptr passed to post buffer\n",
121                 __func__);
122         return;
123     }
124     ComposeLayer composeLayer = {
125         0,
126         HWC2_COMPOSITION_DEVICE,
127         {0, 0, static_cast<int>(displayBufferPtr->m_width),
128          static_cast<int>(displayBufferPtr->m_height)},
129         {0.0f, 0.0f, static_cast<float>(displayBufferPtr->m_width),
130          static_cast<float>(displayBufferPtr->m_height)},
131         HWC2_BLEND_MODE_PREMULTIPLIED,
132         1.0f,
133         {0, 0, 0, 0},
134         static_cast<hwc_transform_t>(0) /* transform */
135     };
136     compose(1, &composeLayer, {std::move(displayBufferPtr)});
137 }
138 
compose(uint32_t numLayers,const ComposeLayer layers[],const std::vector<std::shared_ptr<DisplayBufferInfo>> & composeBuffers)139 void DisplayVk::compose(
140     uint32_t numLayers, const ComposeLayer layers[],
141     const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers) {
142     if (!m_swapChainStateVk || !m_compositorVk || !m_surfaceState) {
143         ERR("%s(%s:%d): Haven't bound to a surface, can't compose color "
144             "buffer.\n",
145             __FUNCTION__, __FILE__, static_cast<int>(__LINE__));
146         return;
147     }
148 
149     auto &surfaceState = *m_surfaceState;
150     std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers;
151     for (int i = 0; i < numLayers; ++i) {
152         if (!composeBuffers[i]) {
153             fprintf(
154                 stderr,
155                 "%s: warning: null ptr passed to compose buffer for layer %d\n",
156                 __func__, i);
157             continue;
158         }
159         const auto &db = *composeBuffers[i];
160         if (!canComposite(db.m_vkFormat)) {
161             ERR("%s(%s:%d): Can't composite the DisplayBuffer(0x%" PRIxPTR
162                 "). The image(VkFormat = %" PRIu64 ") can't be sampled from.\n",
163                 __FUNCTION__, __FILE__, static_cast<int>(__LINE__),
164                 reinterpret_cast<uintptr_t>(&db),
165                 static_cast<uint64_t>(db.m_vkFormat));
166             continue;
167         }
168         auto layer = ComposeLayerVk::createFromHwc2ComposeLayer(
169             m_compositionVkSampler, composeBuffers[i]->m_vkImageView, layers[i],
170             composeBuffers[i]->m_width, composeBuffers[i]->m_height,
171             surfaceState.m_width, surfaceState.m_height);
172         composeLayers.emplace_back(std::move(layer));
173     }
174 
175     if (composeLayers.empty()) {
176         return;
177     }
178 
179     VK_CHECK(m_vk.vkWaitForFences(m_vkDevice, 1, &m_frameDrawCompleteFence,
180                                   VK_TRUE, UINT64_MAX));
181     uint32_t imageIndex;
182     VK_CHECK(m_vk.vkAcquireNextImageKHR(
183         m_vkDevice, m_swapChainStateVk->getSwapChain(), UINT64_MAX,
184         m_imageReadySem, VK_NULL_HANDLE, &imageIndex));
185 
186     if (compareAndSaveComposition(imageIndex, numLayers, layers,
187                                   composeBuffers)) {
188         auto composition =
189             std::make_unique<Composition>(std::move(composeLayers));
190         m_compositorVk->setComposition(imageIndex, std::move(composition));
191     }
192 
193     auto cmdBuff = m_compositorVk->getCommandBuffer(imageIndex);
194 
195     VK_CHECK(m_vk.vkResetFences(m_vkDevice, 1, &m_frameDrawCompleteFence));
196     VkPipelineStageFlags waitStages[] = {
197         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
198     VkSubmitInfo submitInfo = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
199                                .waitSemaphoreCount = 1,
200                                .pWaitSemaphores = &m_imageReadySem,
201                                .pWaitDstStageMask = waitStages,
202                                .commandBufferCount = 1,
203                                .pCommandBuffers = &cmdBuff,
204                                .signalSemaphoreCount = 1,
205                                .pSignalSemaphores = &m_frameDrawCompleteSem};
206     VK_CHECK(m_vk.vkQueueSubmit(m_compositorVkQueue, 1, &submitInfo,
207                                 m_frameDrawCompleteFence));
208 
209     auto swapChain = m_swapChainStateVk->getSwapChain();
210     VkPresentInfoKHR presentInfo = {.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
211                                     .waitSemaphoreCount = 1,
212                                     .pWaitSemaphores = &m_frameDrawCompleteSem,
213                                     .swapchainCount = 1,
214                                     .pSwapchains = &swapChain,
215                                     .pImageIndices = &imageIndex};
216     VK_CHECK(m_vk.vkQueuePresentKHR(m_swapChainVkQueue, &presentInfo));
217     VK_CHECK(m_vk.vkWaitForFences(m_vkDevice, 1, &m_frameDrawCompleteFence,
218                                   VK_TRUE, UINT64_MAX));
219 }
220 
canComposite(VkFormat format)221 bool DisplayVk::canComposite(VkFormat format) {
222     auto it = m_canComposite.find(format);
223     if (it != m_canComposite.end()) {
224         return it->second;
225     }
226     VkFormatProperties formatProps = {};
227     m_vk.vkGetPhysicalDeviceFormatProperties(m_vkPhysicalDevice, format,
228                                              &formatProps);
229     bool res =
230         formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
231     m_canComposite.emplace(format, res);
232     return res;
233 }
234 
compareAndSaveComposition(uint32_t renderTargetIndex,uint32_t numLayers,const ComposeLayer layers[],const std::vector<std::shared_ptr<DisplayBufferInfo>> & composeBuffers)235 bool DisplayVk::compareAndSaveComposition(
236     uint32_t renderTargetIndex, uint32_t numLayers, const ComposeLayer layers[],
237     const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers) {
238     if (!m_surfaceState) {
239         ERR("%s(%s:%d): Haven't bound to a surface, can't compare and save "
240             "composition\n",
241             __FUNCTION__, __FILE__, static_cast<int>(__LINE__));
242         ::abort();
243     }
244     auto [iPrevComposition, compositionNotFound] =
245         m_surfaceState->m_prevCompositions.emplace(renderTargetIndex, 0);
246     auto &prevComposition = iPrevComposition->second;
247     bool compositionChanged = false;
248     if (numLayers == prevComposition.size()) {
249         for (int i = 0; i < numLayers; i++) {
250             if (composeBuffers[i] == nullptr) {
251                 // If the display buffer of the current layer doesn't exist, we
252                 // check if the layer at the same index in the previous
253                 // composition doesn't exist either.
254                 if (prevComposition[i] == nullptr) {
255                     continue;
256                 } else {
257                     compositionChanged = true;
258                     break;
259                 }
260             }
261             if (prevComposition[i] == nullptr) {
262                 // If the display buffer of the current layer exists but the
263                 // layer at the same index in the previous composition doesn't
264                 // exist, the composition is changed.
265                 compositionChanged = true;
266                 break;
267             }
268             const auto &prevLayer = *prevComposition[i];
269             const auto prevDisplayBufferPtr = prevLayer.m_displayBuffer.lock();
270             // prevLayer.m_displayBuffer is a weak pointer, so if
271             // prevDisplayBufferPtr is null, the color buffer
272             // prevDisplayBufferPtr pointed to should have been released or
273             // re-allocated, and we should consider the composition is changed.
274             // If prevDisplayBufferPtr exists and it points to the same display
275             // buffer as the input composeBuffers[i] we consider the composition
276             // not changed.
277             if (!prevDisplayBufferPtr ||
278                 prevDisplayBufferPtr != composeBuffers[i]) {
279                 compositionChanged = true;
280                 break;
281             }
282             const auto &prevHwc2Layer = prevLayer.m_hwc2Layer;
283             const auto hwc2Layer = layers[i];
284             compositionChanged =
285                 (prevHwc2Layer.cbHandle != hwc2Layer.cbHandle) ||
286                 (prevHwc2Layer.composeMode != hwc2Layer.composeMode) ||
287                 (prevHwc2Layer.displayFrame.left !=
288                  hwc2Layer.displayFrame.left) ||
289                 (prevHwc2Layer.displayFrame.top !=
290                  hwc2Layer.displayFrame.top) ||
291                 (prevHwc2Layer.displayFrame.right !=
292                  hwc2Layer.displayFrame.right) ||
293                 (prevHwc2Layer.displayFrame.bottom !=
294                  hwc2Layer.displayFrame.bottom) ||
295                 (prevHwc2Layer.crop.left != hwc2Layer.crop.left) ||
296                 (prevHwc2Layer.crop.top != hwc2Layer.crop.top) ||
297                 (prevHwc2Layer.crop.right != hwc2Layer.crop.right) ||
298                 (prevHwc2Layer.crop.bottom != hwc2Layer.crop.bottom) ||
299                 (prevHwc2Layer.blendMode != hwc2Layer.blendMode) ||
300                 (prevHwc2Layer.alpha != hwc2Layer.alpha) ||
301                 (prevHwc2Layer.color.r != hwc2Layer.color.r) ||
302                 (prevHwc2Layer.color.g != hwc2Layer.color.g) ||
303                 (prevHwc2Layer.color.b != hwc2Layer.color.b) ||
304                 (prevHwc2Layer.color.a != hwc2Layer.color.a) ||
305                 (prevHwc2Layer.transform != hwc2Layer.transform);
306             if (compositionChanged) {
307                 break;
308             }
309         }
310     } else {
311         compositionChanged = true;
312     }
313     bool needsSave = compositionNotFound || compositionChanged;
314     if (needsSave) {
315         prevComposition.clear();
316         for (int i = 0; i < numLayers; i++) {
317             if (composeBuffers[i] == nullptr) {
318                 prevComposition.emplace_back(nullptr);
319                 continue;
320             }
321             auto layer = std::make_unique<SurfaceState::Layer>();
322             layer->m_hwc2Layer = layers[i];
323             layer->m_displayBuffer = composeBuffers[i];
324             prevComposition.emplace_back(std::move(layer));
325         }
326     }
327     return needsSave;
328 }
329 
DisplayBufferInfo(const goldfish_vk::VulkanDispatch & vk,VkDevice vkDevice,uint32_t width,uint32_t height,VkFormat format,VkImage image)330 DisplayVk::DisplayBufferInfo::DisplayBufferInfo(
331     const goldfish_vk::VulkanDispatch &vk, VkDevice vkDevice, uint32_t width,
332     uint32_t height, VkFormat format, VkImage image)
333     : m_vk(vk),
334       m_vkDevice(vkDevice),
335       m_width(width),
336       m_height(height),
337       m_vkFormat(format),
338       m_vkImageView(VK_NULL_HANDLE) {
339     VkImageViewCreateInfo imageViewCi = {
340         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
341         .image = image,
342         .viewType = VK_IMAGE_VIEW_TYPE_2D,
343         .format = format,
344         .components = {.r = VK_COMPONENT_SWIZZLE_IDENTITY,
345                        .g = VK_COMPONENT_SWIZZLE_IDENTITY,
346                        .b = VK_COMPONENT_SWIZZLE_IDENTITY,
347                        .a = VK_COMPONENT_SWIZZLE_IDENTITY},
348         .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
349                              .baseMipLevel = 0,
350                              .levelCount = 1,
351                              .baseArrayLayer = 0,
352                              .layerCount = 1}};
353     VK_CHECK(m_vk.vkCreateImageView(m_vkDevice, &imageViewCi, nullptr,
354                                     &m_vkImageView));
355 }
356 
~DisplayBufferInfo()357 DisplayVk::DisplayBufferInfo::~DisplayBufferInfo() {
358     m_vk.vkDestroyImageView(m_vkDevice, m_vkImageView, nullptr);
359 }
360