Vulkan API — урок 31. Изменение размеров окна (+листинг)

Изменение размеров окна

Продолжая тему прошлого урока, теперь нам нужно просто отловить момент, когда необходимо заново создавать swap chain, вызывать recreateSwapChain. Наиболее распространенная причина вызова этой функции – изменение размеров окна. Итак, для начала предоставим возможность изменять размер окна. Изменим функцию initWindow f, что бы та более не содержала строку GLFW_RESIZABLE, или измените значение с GLFW_FALSE на GLFW_TRUE.

void initWindow() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

    window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);

    glfwSetWindowUserPointer(window, this);
    glfwSetWindowSizeCallback(window, HelloTriangleApplication::onWindowResized);
}

...

static void onWindowResized(GLFWwindow* window, int width, int height) {
    if (width == 0 || height == 0) return;

    HelloTriangleApplication* app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
    app->recreateSwapChain();
}

Функция glfwSetWindowSizeCallback может быть использована для указания обратного вызова события изменения размера окна. К сожалению она принимает только указатель на функцию в качестве аргумента, потому не получится напрямую использовать функцнию-член. Но GLFW позволяет лишь хранить произвольный указатель в окне объекта: glfwSetWindowUserPointer, так что мы можем указать статистичский член класса и получить обратно экземпляр оригинального класса, ну а дальше все и так понятно. Вот только все это проделывать не стоит, когда размер окна равен нулю (например оно свернуто), это не приведет ни к чему хорошему.

Проблемы со swap chain

Так же во время представления вулкан может сообщить нам о том, что swap chain более не является совместимой. Функции vkAcquireNextImageKHR и vkQueuePresentKHR  могут вернуть следующие значения для того, указать на это:

  • VK_ERROR_OUT_OF_DATE_KHR: swap chain стала несовместима с поверхностью и более не может быть использована для рендеринга.
  • VK_SUBOPTIMAL_KHR: swap chain может быть использована для представления на поверхности, но более в точности не соответствуют свойствам поверхности. Например платформа может подогнать размер изображения под размер окна.
VkResult result = vkAcquireNextImageKHR(device, swapChain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);

if (result == VK_ERROR_OUT_OF_DATE_KHR) {
    recreateSwapChain();
    return;
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
    throw std::runtime_error("failed to acquire swap chain image!");
}

Если swap chain окажется устаревшим при попытке получить изображение, тогда она более не способна работать. Поэтому мы должны немедленно восстановить swap chain.

Можно проделать все то же, если настройки swap chain не оптимальны, но изображение уже получено и я бы лучше в текущей итерации все доделал как есть, а в конце пересоздать swap chain.

result = vkQueuePresentKHR(presentQueue, &presentInfo);

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
    recreateSwapChain();
} else if (result != VK_SUCCESS) {
    throw std::runtime_error("failed to present swap chain image!");
}

Функция vkQueuePresentKHR возвращает все те же значения. В случае возникновения двух описанных ранее сообщений мы можем сразу же пересоздать swap chain.

Далее проследует небольшая серия уроков про буфер вершин, ну а пока вот листинг.

Main Admin

2 Comments

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *