모던 Vulkan (C++ 버전) 시리즈의 두 번째 글입니다. 이번 글에서는 인스턴스를 생성하는 과정을 Vulkan-HPP와 Modern C++ 스타일로 재작성해보겠습니다. 이전 입문 시리즈에서 C 스타일로 인스턴스를 만들고 Validation Layer를 설정했던 과정을 다시 돌아보며, 이번에는 RAII를 활용한 vk::UniqueInstance, 예외 처리 모드 등을 적용하여 더 깔끔하고 유지보수하기 쉬운 코드를 작성하는 방법을 제시합니다.
목표
- Vulkan C API 스타일로 작성했던 인스턴스 생성 코드를 Vulkan-HPP 기반 C++ 코드로 재구성
- vk::ApplicationInfo, vk::InstanceCreateInfo 등을 이용하여 Application, Engine, API 버전 정보 설정
- vk::createInstanceUnique()를 통한 RAII 기반 인스턴스 관리
- Validation Layer와 Extension 설정 시 C++ STL 컨테이너와 enum class 활용
- 예외 처리 모드 사용 여부에 따른 에러 처리 전략 예시
기본 개념 복습
Vulkan 인스턴스 생성 시 해야 할 일:
VkApplicationInfo
를 통해 앱 정보(앱 이름, 엔진 이름, Vulkan 버전) 설정VkInstanceCreateInfo
에 Validation Layer와 Extension 목록을 지정vkCreateInstance
로 인스턴스 생성 후 필요 시vkDestroyInstance
호출
C 스타일에서는 이러한 과정을 구조체 초기화와 함수 호출로 처리했습니다. 이제 Vulkan-HPP로 전환하면:
vk::ApplicationInfo
,vk::InstanceCreateInfo
와 같은 C++ 클래스로 구조체 초기화 대체vk::createInstance
또는vk::createInstanceUnique
를 통해 인스턴스 생성- RAII를 사용하면 소멸 시 자동 정리
- Validation Layer와 Extension을
std::vector<std::string>
으로 관리한 뒤.data()
로 넘기거나std::vector<const char*>
를 만들어 넘기면 깔끔하게 처리 가능
예외 처리 모드 활용
Vulkan-HPP는 기본적으로 예외를 던지지 않는 모드로 동작하지만, 컴파일 옵션을 통해 예외 모드를 활성화할 수 있습니다. 예외 모드에서는 vk::createInstanceUnique
호출이 실패하면 vk::SystemError
예외를 던져 에러 처리를 단순화합니다. 예외를 사용하지 않고 싶다면 auto [result, instance] = vk::createInstance(...)
형태로 결과를 명시적으로 체크할 수도 있습니다.
여기서는 예외 모드를 사용한다고 가정합니다. (VULKAN_HPP_NO_EXCEPTIONS
를 정의하지 않으면 예외 모드 활성화)
코드 예제
디렉토리 구조
my_vulkan_hpp_instance/
├─ CMakeLists.txt
├─ src/
│ └─ main.cpp
└─ build/
main.cpp 코드
#include <iostream>
#include <vector>
#include <vulkan/vulkan.hpp>
int main() {
// 앱 정보
vk::ApplicationInfo appInfo(
"MyVulkanApp",
1,
"MyEngine",
1,
VK_API_VERSION_1_3
);
// Validation Layer와 Extension 설정
// 예: Validation Layer 활성화 시 "VK_LAYER_KHRONOS_validation" 사용
std::vector<const char*> layers = { "VK_LAYER_KHRONOS_validation" };
// Extension은 보통 VK_EXT_debug_utils 등을 추가할 수 있음
// 여기서는 예시로 기본 Extension만 (실제 시스템에 맞게 수정 필요)
std::vector<const char*> extensions = {
"VK_EXT_debug_utils"
};
vk::InstanceCreateInfo createInfo(
{}, // flags
&appInfo, // pApplicationInfo
(uint32_t)layers.size(), layers.data(),
(uint32_t)extensions.size(), extensions.data()
);
try {
// RAII 기반 인스턴스 생성
vk::UniqueInstance instance = vk::createInstanceUnique(createInfo);
// 인스턴스 생성 성공
std::cout << "Vulkan Instance created successfully with Vulkan-HPP!\n";
// instance가 스코프를 벗어나면 자동으로 vkDestroyInstance 호출
} catch (const vk::SystemError& err) {
std::cerr << "Failed to create Vulkan Instance: " << err.what() << "\n";
return 1;
}
return 0;
}
CMakeLists.txt 예제
cmake_minimum_required(VERSION 3.10)
project(vulkan_hpp_instance)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Vulkan REQUIRED)
add_executable(vulkan_hpp_instance src/main.cpp)
target_include_directories(vulkan_hpp_instance PRIVATE ${Vulkan_INCLUDE_DIRS})
target_link_libraries(vulkan_hpp_instance Vulkan::Vulkan)
빌드 및 실행
mkdir build
cd build
cmake ..
make
./vulkan_hpp_instance
정상적으로 인스턴스가 생성되면 “Vulkan Instance created successfully with Vulkan-HPP!”가 출력됩니다. 예외를 던질 상황(예: 잘못된 Layer나 Extension 이름을 주면) vk::SystemError 예외를 catch 블록에서 처리할 수 있습니다.
주요 포인트
- RAII를 통한 인스턴스 자동 정리: vk::UniqueInstance
- vector, string 등 STL 컨테이너를 활용해 Layer, Extension 관리 간소화
- 예외 처리 모드로 에러 처리 단순화 (try/catch)
- 코드가 C 스타일 대비 훨씬 간결하고 안전해짐
정리 및 다음 글 예고
이번 글에서는 인스턴스 생성 과정을 Vulkan-HPP 기반 Modern C++ 스타일로 재작성했습니다. RAII, 예외 처리, STL 컨테이너 등을 활용해 코드를 단순화하고 안전성을 높일 수 있음을 확인했습니다.
다음 글(#3)에서는 물리 디바이스 열람 및 로지컬 디바이스, 큐 확보 과정을 다시 C++ 스타일로 재구현해보겠습니다. 이전에는 C API로 반복문과 if문을 통해 디바이스를 선택했지만, 이제는 Vulkan-HPP와 RAII로 한층 깔끔한 코드를 작성할 수 있을 것입니다.
'개발 이야기 > Vulkan' 카테고리의 다른 글
[모던 Vulkan (C++ 버전)] #4: 커맨드 버퍼, 커맨드 풀, 큐 제출 (RAII 기반) (0) | 2024.12.19 |
---|---|
[모던 Vulkan (C++ 버전)] #3: 물리 디바이스 선택 및 로지컬 디바이스, 큐 확보 (RAII 적용) (0) | 2024.12.19 |
[모던 Vulkan (C++ 버전)] #1: Vulkan-HPP와 Modern C++ 개요 (0) | 2024.12.19 |
모던 C++와 Vulkan의 만남: Vulkan-HPP로 코드 품질 높이기 (0) | 2024.12.19 |
[Vulkan으로 GPGPU 시작하기] #10: 마무리와 다음 단계로의 길잡이 (1) | 2024.12.19 |