Vulkan 오브젝트 이해하기

취미로 프로그래밍을 할 수 있을 정도로 회복된 요즘, 다시 Vulkan 튜토리얼을 보면서 복습 중입니다. 예제를 돌려보면서 어떤 식으로 내가 원하는 형태로 추상화를 할 수 있을까 고민하다가, Vulkan 내 오브젝트 간의 의존성이 어떻게 되는지를 정리를 해보는데, ‘그런 일을 누군가는 이미 하지 않았을까’ 싶어서 검색을 좀 했더니 좋은 글이 나오더군요. 공부하는 차원에서 오랜만에 번역을 해봤습니다.

원문 보기: https://gpuopen.com/learn/understanding-vulkan-objects

Vulkan 오브젝트 이해하기

Vulkan API를 배우는 중요한 부분은 (다른 API와 마찬가지로) 어떤 종류의 오브젝트가 정의되어 있는지, 이들이 무엇을 나타내고 서로 어떻게 연관되어 있는지 이해하는 것입니다. 이를 돕기 위해서 우리는 모든 Vulkan 오브젝트들과 이들의 관계성, 특히 어떤 오브젝트로부터 다른 오브젝트를 만드는지에 대한 순서를 보여주는 다이어그램을 만들었습니다.

각각의 Vulkan 오브젝트는 Vk라는 앞글자가 붙은 특정 타입의 값입니다. 이 앞글자는 다이어그램의 간소화를 위해 생략하였으며 이는 함수 이름 앞에 붙은 vk도 마찬가지입니다. 예를 들면 다이어그램의 Sampler는 VkSampler라는 Vulkan 오브젝트 타입이 있다는 의미입니다. 이러한 타입들은 포인터나 보통의 숫자처럼 취급되어서는 안됩니다. 이 값들을 어떤 방식으로든 해석하려고 하면 안됩니다. 그저 이들을 명확한 핸들로서 취급하고, 함수의 파라미터로 넘기고, 당연하겠지만 필요 없어질 경우 제거하는 것만 잊지 않으면 됩니다. 녹색 바탕의 오브젝트들은 자체 타입이 없고, 대신 부모 오브젝트 내의 uint32_t 타입 정수형 인덱스 값으로 표현됩니다. QueryPool의 Query 같은 것들이 그렇습니다.

화살표가 붙은 실선은 생성 순서를 나타냅니다. 예를 들어 DescriptorSet을 만들기 위해서는 이미 만들어진 DescriptorPool을 지정해야 합니다. 다이아몬드가 붙은 실선은 구성(composition)을 나타내는데, 이는 그 오브젝트가 부모 오브젝트에 이미 존재하므로 별도로 만들 필요가 없이 그냥 가져올 수 있다는 뜻입니다. 예를 들면 Instance 오브젝트로부터 PhysicalDevice 오브젝트들을 열거할 수 있습니다. 점선은 그 밖의 관계를 의미합니다. CommandBuffer에 대한 다양한 명령들을 제출하는 것이 그렇습니다.

이 다이어그램은 크게 세 부분으로 나뉘어져 있습니다. 각 부분은 빨간색으로 표시된 메인 오브젝트를 가지고 있습니다. 다른 모든 오브젝트들은 이 메인 오브젝트로부터 직접적으로 혹은 간접적으로 생성됩니다. 예를 들면 Sampler를 생성하는 vkCreateSampler 함수는 VkDevice를 첫 번째 파라미터로 받습니다. 간소화를 위해서 메인 오브젝트와의 관계성은 다이어그램에 그리지 않았습니다.

vulkan_diagram

모든 오브젝트들에 대하여 간략한 설명을 해보겠습니다:

Binding slot Resource
0 vertex shader stage에서 활용할 유니폼 버퍼 (DirectX의 constant buffer)
1 fragment shader stage에서 사용할 유니폼 버퍼
2 샘플링된 이미지
3 fragment shader stage에서 사용할 샘플러

이제 여러분은 GPU가 모든 프레임에서 실질적인 작업을 수행하도록 하기 위해서 (가능한 병렬적으로!) Vulkan 함수를 어떻게 호출해야 하는지 배울 필요가 있겠습니다. 그러면 현대적인 GPU가 제공하는 훌륭하고 유연한 연산 성능을 모두 활용할 여러분만의 방식을 갖게 될 것입니다.