이 글은 Vulkan을 학습하는 개발자의 관점에서, 창(Window)과 화면 출력(Presentation)의 관계를 사실 위주로 정리한 기록입니다.
핵심 요약: Vulkan과 창(Window)의 관계
Vulkan은 렌더링 API일 뿐, 운영체제(OS)의 창(Window)을 직접 만들지 않습니다. 대신, 렌더링 결과를 화면에 표시하기 위해 OS가 관리하는 창에 연결해야 합니다. 이 연결 과정을 WSI(Window System Integration) 라 부르며, 핵심적인 역할을 하는 것이 바로 VkSurfaceKHR입니다.
GLFW 와 같은 라이브러리는 이 연결 과정을 간소화하는 도구입니다.
주요 개념 정리
| 개념 (Concept) | 설명 (Description) |
|---|---|
| Window | OS가 관리하는 “화면에 표시되는 영역” 그 자체입니다. Vulkan 객체가 아닙니다. |
Surface (VkSurfaceKHR) | OS의 Window와 Vulkan을 이어주는 “연결 고리” 역할을 하는 WSI 핸들입니다. |
Swapchain (VkSwapchainKHR) | 화면에 표시될 “이미지들의 큐(Queue)” 입니다. Surface에 바인딩되어 렌더링 결과를 전달합니다. |
| Present | 렌더링을 마친 스왑체인 이미지를 화면에 “실제로 보여달라” 고 요청하는 작업 (vkQueuePresentKHR)입니다. |
GLFW의 역할: 창과 Vulkan의 연결
GLFW는 Vulkan의 렌더링이나 스왑체인 관리에는 관여하지 않으며, 정확히 아래의 역할만 담당합니다.
- 창 생성 및 이벤트 처리:
GLFWwindow*객체를 생성하고, 키보드/마우스 입력이나 창 크기 변경 같은 이벤트를 처리합니다. - Vulkan 인스턴스 확장 조회:
glfwGetRequiredInstanceExtensions함수로 현재 OS 환경에 맞는 Vulkan 확장(VK_KHR_surface등) 목록을 쉽게 얻게 해줍니다. - Surface 생성:
glfwCreateWindowSurface함수를 통해 OS의GLFWwindow*와 Vulkan 인스턴스를 연결하여VkSurfaceKHR핸들을 생성합니다. - OpenGL 비활성화:
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API)를 통해 “이 창은 Vulkan이 쓸 것”이라고 명시합니다.
일반적인 초기화 흐름
- 확장 쿼리:
glfwGetRequiredInstanceExtensions로 현재 플랫폼에 필요한 Surface 관련 확장 목록을 확보합니다. - 인스턴스 생성: 획득한 확장들을 포함하여
VkInstance를 만듭니다. - 창 생성:
glfwCreateWindow로GLFWwindow*를 준비합니다. - Surface 생성:
glfwCreateWindowSurface로VkInstance와GLFWwindow*를 연결해VkSurfaceKHR를 얻습니다. - 물리/논리 디바이스 선택: 생성된 Surface에 렌더링 결과를 Present(표시)할 수 있는 능력을 가진 GPU와 큐(Queue)를 찾아서
VkDevice를 생성합니다. - 스왑체인 구성: Surface의 속성(포맷, 크기 등)에 맞춰 스왑체인을 생성합니다.
- 메인 루프: 이벤트 처리 → 렌더링 커맨드 기록 및 제출 → Present 요청을 반복합니다.
주요 고려사항 및 팁
플랫폼 관련 메모
- macOS (MoltenVK): 환경에 따라
VK_EXT_metal_surface확장이 필요하며,VK_KHR_portability_enumeration관련 설정이 필요합니다. - DPI 스케일링: 환경에 따라 창의 크기(Screen coordinates)와 실제 픽셀 크기(Framebuffer)가 다릅니다. 스왑체인의 크기는
glfwGetFramebufferSize를 기준으로 설정합니다.
자주 마주치는 함정과 팁
- 큐 패밀리 분리: 그래픽 처리용 큐와 Present용 큐가 동일하지 않은 환경을 고려해, 각각의 인덱스와 핸들을 별도로 관리합니다.
- 창 리사이즈: 창 크기가 변경되면 스왑체인을 다시 만들어야 합니다.
vkQueuePresentKHR가VK_ERROR_OUT_OF_DATE_KHR또는VK_SUBOPTIMAL_KHR을 반환하면 이를 처리해야 합니다. - 유효성 검사 (Validation): 인스턴스나 디바이스 생성 시 필요한 확장이나 레이어를 빠뜨리는 실수가 잦습니다. 초기화 단계의 로그를 꼼꼼히 확인하는 것이 중요합니다.
대안 라이브러리
대안으로 SDL2 를 사용하거나, Win32(Windows), XCB(Linux), Metal(macOS) 등 각 플랫폼의 네이티브 API를 직접 사용합니다. 어떤 방법을 쓰든 핵심은 “OS 창을 생성하고, 그것으로 VkSurfaceKHR를 생성하는 능력” 을 갖추는 것입니다.
이 게시물은 학습한 내용을 바탕으로 초안을 작성한 뒤, LLM의 도움을 받아 내용을 검수하고 다듬어 완성되었습니다.