이전 글 : Drawing - Rendering and presentation
다음 글 : Vertex input description
Swap chain recreation
스왑 체인 레크리에이션
Introduction
우리는 이제 삼각형을 성공적으로 그렸지만 아직 제대로 처리하지 못하는 상황이 있습니다. 스왑 체인이 더 이상 서피스에 호환되지 않을때가 있습니다. 이 문제를 일으킬 수 있는 이유 중 하나는 창 크기가 변하는 것입니다. 우리는 이러한 사건이 발생하면 스왑 체인을 다시 만들어야 합니다.
Recreating the swap chain
스왑 체인 다시 만들기
createSwapChain을 호출하는 새로운 recreateSwapChain 함수를 만들고 스왑 체인이나 창 크기에 의존하는 객체의 모든 생성 함수를 만듭니다.
void recreateSwapChain() { |
마지막 챕터와 마찬가지로 vkDeviceWaitIdle 을 호출하기 때문에 여전히 사용중인 리소스를 만지지 않아야 합니다.
분명히 우리가 해야 할 첫 번째 일은 스왑 체인 자체를 다시 만드는 것입니다.
이미지 뷰는 스왑 체인 이미지를 직접 기반으로 하므로 다시 만들어야 합니다.
렌더 패스는 스왑 체인 이미지 형식에 따라 다르기 때문에 다시 작성해야 합니다.
스왑 체인 이미지 형식은 창 크기 조정과 같은 작업 중에 변경되는 경우는 거의 없지만 여전히 처리해야 합니다.
뷰포트 및 시저스 크기는 그래픽 파이프 라인 생성 중에 지정되므로 파이프 라인도 다시 작성해야합니다. 뷰포트와 시저 사각형에 동적 상태를 사용하여 이를 피할 수 있습니다.
마지막으로 프레임 버퍼와 명령 버퍼는 스왑 체인 이미지에 직접 의존합니다.
이러한 객체들을 다시 만들기 전에 기존의 리소스를 정리해야 하는데 이를 하려면 cleanup 코드 중 일부를 recreateSwapChain 함수에서 호출 할 수있는 별도의 함수로 옮겨야 합니다. 그것을 cleanupSwapChain 이라고 부르도록 하겠습니다.
void cleanupSwapChain() { |
스왑 체인 새로 고침의 일부로 다시 생성 된 모든 객체의 정리 코드를 cleanup() 에서 cleanupSwapChain() 으로 이동합니다.
void cleanupSwapChain() { |
명령 풀을 처음부터 다시 만들 수는 있지만, 그것은 낭비입니다. 대신 vkFreeCommandBuffers 함수를 사용하여 기존 명령 버퍼를 정리하도록 선택했습니다. 이렇게하면 기존 풀을 다시 사용하여 새 명령 버퍼를 할당 할 수 있습니다.
이것이 스왑 체인을 다시 만드는 데 필요한 전부입니다! 그러나 이 방법의 단점은 새 스왑 체인을 만들기 전에 모든 렌더링을 중지해야 한다는 것입니다. 이전 스왑 체인의 이미지에 대한 명령을 그리는 동안 여전히 새로운 스왑 체인을 만들 수 있습니다. 이전 스왑 체인을 VkSwapchainCreateInfoKHR 구조체의 oldSwapChain 필드에 전달하고 사용을 마친 즉시 이전 스왑 체인을 삭제해야 합니다.
Window resizing
이제 스왑 체인 을 다시 만들어야 하는 필요가 있는 시기를 파악하고 새로운 recreateSwapChain 함수를 호출하면 됩니다. 가장 일반적인 조건 중 하나는 창 크기를 조정하는 것입니다. 창 크기를 조정하고 해당 이벤트를 처리 해 봅시다. initWindow 함수에 GLFW_RESIZABLE 행을 포함 시키거나 해당 인수를 GLFW_FALSE에서 GLFW_TRUE로 변경하십시오.
void initWindow() { |
glfwSetWindowSizeCallback 함수를 사용하여 window resize 이벤트에 대한 콜백을 지정할 수 있습니다. 불행히도 인수로만 함수 포인터를 받아들이므로 멤버 함수를 직접 사용할 수는 없습니다. 다행히 GLFW를 사용하면 glfwSetWindowUserPointer를 사용하여 창 객체에 임의의 포인터를 저장할 수 있으므로 정적 클래스 멤버를 지정하고 glfwGetWindowUserPointer 를 사용하여 원래 클래스 인스턴스를 다시 가져올 수 있습니다. 그런 다음 윈도우의 크기가 0이 아닌 경우에만 recreateSwapChain을 호출 할 수 있습니다. 이 경우는 창이 최소화되어 스왑 체인 작성이 실패 할 수 있습니다.
chooseSwapExtent 함수는 초기 WIDTH 및 HEIGHT 대신 창의 현재 너비 및 높이를 고려하여 업데이트해야 합니다.
int width, height; |
Suboptimal or out-of-date swap chain
차선 또는 만료 된 스왑 체인
또한 Vulkan은 프리젠테이션 도중 스왑 체인이 더 이상 호환되지 않는다고 알려 줄 수 있습니다. vkAcquireNextImageKHR 및 vkQueuePresentKHR 함수는 이를 나타내기 위해 다음 특수 값을 반환 할 수 있습니다.
VK_ERROR_OUT_OF_DATE_KHR : 스왑 체인이 서피스와 호환되지 않아 더 이상 렌더링에 사용할 수 없습니다.
VK_SUBOPTIMAL_KHR : 스왑 체인을 사용하여 표면에 성공적으로 표시 할 수 있지만 표면 특성이 더 이상 정확하게 일치하지 않습니다. 예를 들어, 플랫폼은 이미지를 창의 크기에 맞게 크기 조정할 수 있습니다.
VkResult result = vkAcquireNextImageKHR(device, swapChain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); |
스왑 체인이 이미지를 획득하려고 시도 할 때 오래된 것으로 판명되면 더 이상 프레즌테이션 할 수 없습니다. 따라서 우리는 즉시 스왑 체인을 다시 만들고 다음 drawFrame 호출을 다시 시도해야 합니다.
스왑 체인이 부차적 인 경우 이를 수행하기로 결정할 수도 있지만 이미 이미지를 획득했기 때문에 계속 진행하도록 선택했습니다. VK_SUCCESS와 VK_SUBOPTIMAL_KHR 모두 "success" 리턴 코드로 간주됩니다.
result = vkQueuePresentKHR(presentQueue, &presentInfo); |
vkQueuePresentKHR 함수는 같은 의미의 동일한 값을 반환합니다. 이 경우 최적의 결과를 원하기 때문에 최적이 아닌 경우 스왑 체인을 다시 만듭니다. 프레임 버퍼를 실행하고 창 크기를 조정하여 프레임 버퍼가 실제로 창과 함께 제대로 크기가 조정되었는지 확인하십시오.
축하합니다. 이제 첫 번째로 잘된 Vulkan 프로그램을 마쳤습니다!
다음 장에서는 버텍스 쉐이더에 직접 코딩 된 버텍스 정보를 없애고 실제로 버텍스 버퍼를 사용할 것입니다.
C++ code / Vertex shader / Fragment shader
이전 글 : Drawing - Rendering and presentation
다음 글 : Vertex input description
'Vulkan' 카테고리의 다른 글
Vertex buffer creation (0) | 2018.01.25 |
---|---|
Vertex input description (0) | 2018.01.25 |
Drawing - Rendering and presentation (0) | 2018.01.25 |
Drawing - Command buffers (1) | 2018.01.25 |
Drawing - Framebuffers (1) | 2018.01.24 |