가장 먼저 인스턴스를 생성하여 Vulkan 라이브러리를 초기화해야 합니다. 인스턴스는 어플리케이션과 Vulkan 라이브러리 간의 연결이며, 어플리케이션에 대한 몇가지 정보를 드라이버에 지정하는 작업이 포함됩니다.
createInstance 함수를 추가하고 initVulkan 함수에서 호출합니다.
void initVulkan() {
createInstance();
}
추가로 인스턴스에 대한 핸들을 보유할 데이터 멤버를 추가합니다:
private:
VkInstance instance;
이제 인스턴스를 생성하기 위해 우리들의 어플리케이션에 대한 몇가지 정보를 구조체에 추가해야 합니다. 이 데이터는 기술적으로 선택사항이지만, 특정 어플리케이션을 최적화하기 위해 드라이버에게 유용한 정보를 제공할 수도 있습니다. (특정 특수 동작으로 잘 알려진 그래픽 엔진을 사용하기 때문에). 이 구조체는 VkApplicationInfo입니다:
void createInstance() {
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
}
앞에서 언급했듯이, Vulkan의 많은 구조체는 sType 멤버에 형식을 명시적으로 지정해야 합니다. 많은 구조체에 있는 것으로 pNext도 있는데, 미래에 확장 정보를 가리킬 수 있는 멤버입니다. 일단은 nullPtr로 초기화합니다.
Vulkan의 많은 정보들은 함수 매개변수 대신 구조체를 통해 전달이 됩니다. 인스턴스를 생성할 때 충분한 정보를 제공하려면 구조체를 하나 더 채워야 합니다. 다음 구조체는 선택사항이 아니며, Vulkan 드라이버에 전역 확장 및 유효성 검사 계층을 알려줍니다. 전역이란 의미는 특정 장치가 아닌 프로그램 전반에 적용되는 것을 말합니다. 다음 몇 챕터에서 명확해질 것입니다.
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
처음 두 매개변수는 간단합니다. 다음 두 계층은 원하는 전역 확장을 지정합니다. Overview 챕터에서 말했듯이 Vulkan은 플랫폼에 구애받지 않는 API입니다. 즉, 창 시스템과 인터페이스 하려면 확장이 필요하다는 것입니다. GLFW는 우리가 구조체에 전달하기 위해 필요한 여러 확장을 반환하는 내장 함수들을 가지고 있습니다.
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
구조체의 마지막 두 멤버는 활성화할 전역 유효성 검사 계층을 결정합니다. 우리는 다음 챕터에서 더 깊게 볼 것이므로, 지금은 비워두도록 합시다.
createInfo.enabledLayerCount = 0;
이제 Vulkan이 인스턴스를 생성하는데 필요한 모든 것들을 지정했습니다. 드디어 vkCreateInstance를 호출할 수 있습니다.
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
보다시피 Vulkan에서 오브젝트 생성 함수의 매개변수가 따르는 일반적인 패턴은 이렇습니다:
nullptr.