фантомные изображения после перехода с разделенного экрана на полный экран - PullRequest
0 голосов
/ 04 марта 2019

Я пишу игру для Android, используя NDK.Моя игра использует vulkan, если он доступен, и использует OpenGL.

У меня проблема в том, что если вы переведете игру в режим разделенного экрана, когда устройство находится в портретной ориентации, то измените размер игры на полноэкранный режим,изображение игры на старом виде все еще видно.Примечание: выполнение этого с игрой вызывает триггер SurfaceHolder.Callback.surfaceDestroyed (в Java), который, в свою очередь, закрывает мой поток рендеринга в C ++.Мой обратный вызов для surfaceDestroyed сообщает C ++, что поток рендеринга должен быть остановлен, а затем присоединяется к нему.

Я могу исправить это в OpenGL, вызвав glClearColor с любым цветом, а затем вызвать eglSwapBuffers непосредственно перед тем, как поток рендеринга завершит работу.

Это корректное исправление для OpenGL?Есть ли что-то еще, что я должен сделать, чтобы очистить старую поверхность?Я проверил, что ANativeWindow_release вызывается в окне, которое я получаю из ANativeWindow_fromSurface, прежде чем выйти из потока рендеринга.

Затем я попытался сделать то же самое в vulkan и снова столкнулся с проблемами ... Я использовал vkCmdClearColorImage, выполнив командуследующее:

(1) vkQueueWaitIdle (presentQueue)

(2) vkAquireNextImageKHR

(3) инициализировать соответствующий буфер команд с помощью:

(3a) ImageMemoryBarrier VK_IMAGE_LAYOUT_UNDEFINED -> VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0 -> VK_ACCESS_TRANSFER_WRITE_BIT

(3b) vkCmdClearColor VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL

(3с) ImageMemoryBarrier VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_ACCESS_TRANSFER_WRITE_BIT -> VK_ACCESS_MEMORY_READ_BIT

(4)vkQueueSubmit (graphicsQueue ...)

(5) vkQueuePresentKHR (presentQueue ...)

(6) vkQueueWaitIdle (presentQueue)

Я получил 3a, а затем яполучил ошибку в валислой данных о том, что изображение не было создано с флагом использования VK_IMAGE_USAGE_TRANSFER_DST_BIT.Как заставить образы swapchain создаваться с помощью этого бита использования?

Пожалуйста, дайте мне знать, если необходима дополнительная информация.Спасибо!

1 Ответ

0 голосов
/ 04 марта 2019

Вулканская часть говорит сама за себя;есть член imageUsage.Позвольте мне дать вам код:

VkSurfaceCapabilitiesKHR caps;
errco = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( pdev, mySurface, &caps ); if(errco) panic();
if( !(caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) ) panic();

VkSwapchainCreateInfoKHR sci = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
sci.surface = mySurface;
sci.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; // !
// etc

VkSwapchainKHR mySwapchain;
errco = vkCreateSwapchainKHR( dev, &sci, nullptr, &mySwapchain ); if(errco) panic();

Хотя вы, вероятно, не должны делать это в любом случае.Нет причин делать vkCmdClearColorImage.Используйте проход рендеринга для очистки цветных изображений перед тем, как вы собираетесь их записывать (VkAttachmentDescription::loadOp).Он более эффективен, и в качестве бонуса он считается рендером и не требует TRANSFER использования.

Кажется, windowBackgroundFallback должно быть общим решением для этого, если ваше приложение не можетпредоставить новое изображение вовремя.

Лучшее решение избавиться от фантомного изображения - это сказать, чтобы Android не закрывал приложение, если происходит изменение размера экрана.Таким образом, изменение размера экрана может быть выполнено путем воссоздания swapchain и перерисовки игры.Эта статья говорит о настройке android: configChanges в файле манифеста.Следующая настройка не позволяет Android выключать приложение при изменении размера экрана с разделенного на полный экран:

android:configChanges="screenSize|orientation|screenLayout"

...