| 161 | } |
| 162 | |
| 163 | bool VulkanBaseContext::BeginRendering() |
| 164 | { |
| 165 | if (!m_presentAvailable) |
| 166 | return false; |
| 167 | |
| 168 | // We wait for the fences no longer than kTimeoutNanoseconds. If timer is expired skip |
| 169 | // the frame. It helps to prevent freeze on vkWaitForFences in the case of resetting surface. |
| 170 | uint64_t constexpr kTimeoutNanoseconds = 2 * 1000 * 1000 * 1000; |
| 171 | auto res = vkWaitForFences(m_device, 1, &m_fences[m_inflightFrameIndex], VK_TRUE, kTimeoutNanoseconds); |
| 172 | if (res == VK_TIMEOUT) |
| 173 | return false; |
| 174 | |
| 175 | if (res != VK_SUCCESS && res != VK_ERROR_DEVICE_LOST) |
| 176 | CHECK_RESULT_VK_CALL(vkWaitForFences, res); |
| 177 | |
| 178 | CHECK_VK_CALL(vkResetFences(m_device, 1, &m_fences[m_inflightFrameIndex])); |
| 179 | |
| 180 | // Clear resources for the finished inflight frame. |
| 181 | { |
| 182 | for (auto const & h : m_handlers[static_cast<uint32_t>(HandlerType::PostPresent)]) |
| 183 | h.second(m_inflightFrameIndex); |
| 184 | |
| 185 | // Resetting of the default staging buffer is only after the finishing of current |
| 186 | // inflight frame rendering. It prevents data collisions. |
| 187 | m_defaultStagingBuffers[m_inflightFrameIndex]->Reset(); |
| 188 | |
| 189 | // Descriptors can be used only on the thread which renders. |
| 190 | m_objectManager->CollectDescriptorSetGroups(m_inflightFrameIndex); |
| 191 | |
| 192 | CollectMemory(); |
| 193 | } |
| 194 | |
| 195 | m_frameCounter++; |
| 196 | |
| 197 | // FIXME: Infinite timeouts are not supported on Android for vkAcquireNextImageKHR. |
| 198 | // "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented" |
| 199 | // https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/vulkan/libvulkan/swapchain.cpp |
| 200 | res = vkAcquireNextImageKHR(m_device, m_swapchain, std::numeric_limits<uint64_t>::max() /* kTimeoutNanoseconds */, |
| 201 | m_acquireSemaphores[m_inflightFrameIndex], VK_NULL_HANDLE, &m_imageIndex); |
| 202 | // VK_ERROR_SURFACE_LOST_KHR appears sometimes after getting foreground. We suppose rendering can be recovered |
| 203 | // next frame. |
| 204 | if (res == VK_TIMEOUT || res == VK_ERROR_SURFACE_LOST_KHR) |
| 205 | { |
| 206 | vkDeviceWaitIdle(m_device); |
| 207 | DestroySyncPrimitives(); |
| 208 | CreateSyncPrimitives(); |
| 209 | return false; |
| 210 | } |
| 211 | |
| 212 | #if defined(OMIM_OS_MAC) |
| 213 | // MoltenVK returns VK_SUBOPTIMAL_KHR in our configuration, it means that window is not resized that's expected |
| 214 | // in the developer sandbox for macOS |
| 215 | // https://github.com/KhronosGroup/MoltenVK/issues/1753 |
| 216 | if (res == VK_SUBOPTIMAL_KHR) |
| 217 | res = VK_SUCCESS; |
| 218 | #endif |
| 219 | |
| 220 | if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) |
no test coverage detected