Vulkan Samples Tutorial-01-Instance

in #vulkan8 years ago (edited)

https://vulkan.lunarg.com/doc/sdk/1.0.65.1/windows/tutorial/html/index.html
에 있는 내용을 정리하고자 포스팅을 합니다.

The basic Vulkan architecture

diagram을 보면 간결한 구조(?) 입니다. Vulkan Application은 Loader(Vulkan library)로 코드를 짜고
필요에 따라 validation 등의 역할을 하는 layer를 거쳐 GPU driver로 가게 됩니다.

  • Application - Vulkan application 입니다.
  • Loader - Vulkan library로 VkI nstance 생성시 Loader init이 이루어지고 이후 driver load, init을 합니다.
  • Layer - validation 등 다양한 용도로 쓰이며 VkInstance load합니다.
  • Driver - GPU를 제어하는 역할을 합니다. 보통 Loader와 Driver는 vendor(ex: NVidia, AMD, ARM, IMG and etc)에서 제공이 되거나 Mesa와 같이 OpenDDK도 있습니다.

우선 01-init_instance.cpp에서 하는 것은 단순히 VkInstance type의 instance를 생성하는 것입니다. (VkInstance라고 하겠습니다.)

vkCreateInstance

VkInstance 핸들은 아래 함수를 호출해 얻을 수 있습니다.

VkResult vkCreateInstance(
    const VkInstanceCreateInfo*                 pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkInstance*                                 pInstance);

argument부터 return type 모두 Vk 로 시작하네요.
변수 type은 Vk이고, function type은 vk로 시작합니다

VkResult부터 보면 enum type으로 VK_SUCCESS가 나오면 pass지만 그 이외의 상황에서는 왜 문제가 났는지 따져봐야 합니다.
(vulkan.h에서 enum 내용이 무엇이 있는지 볼 수 있습니다.)

VkInstanceCreateInfo

typedef struct VkInstanceCreateInfo {
    VkStructureType             sType;
    const void*                 pNext;
    VkInstanceCreateFlags       flags;
    const VkApplicationInfo*    pApplicationInfo;
    uint32_t                    enabledLayerCount;
    const char* const*          ppEnabledLayerNames;
    uint32_t                    enabledExtensionCount;
    const char* const*          ppEnabledExtensionNames;
} VkInstanceCreateInfo;

모든 struct의 맨 앞에는 다음 2개의 type이 있습니다.

    VkStructureType             sType;
    const void*                 pNext;

sType은 struct의 type이 무엇인지를 정하는데 사용합니다. 예를 들어 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO 이렇게요, 잘못 설정하면 이후 단계에서 예상치 못하는 에러가 발생할 수 있습니다. 그런데 왜 이렇게 struct 설정할 때마다 type을 정해줘야할까요? 이후에 차차 나오겠지만 struct type이 void* 형태로 전달될 경우 이를 확인해 typecasting을 위해서 입니다. 즉, ptr의 맨 처음 값을 확인해 어떤 type인지 확인하고 그에 맞는 struct에 맞춰 typecasting을 하겠지요.

pNext은 sampe 에선 사용하지 않습니다. extension-specific information 전달시 사용한다고 합니다.

sample에선 pApplicationInfo를 제외한 다른 field 값을 사용하지 않으므로 다 0이나 NULL처리를 하면 됩니다.

VkApplicationInfo

VkInstanceCreateInfo struct에서 VkApplicationInfo struct를 품고 있습니다.

typedef struct VkApplicationInfo {
    VkStructureType    sType;
    const void*        pNext;
    const char*        pApplicationName;
    uint32_t           applicationVersion;
    const char*        pEngineName;
    uint32_t           engineVersion;
    uint32_t           apiVersion;
} VkApplicationInfo;

sType, pNext는 위와상동이며, pApplicationName 부터 engineVersion은 free-form fields로 원하는 목적에 맞춰 채우면 됩니다. (상황에 따라 driver behavior에 영향을 준다고 합니다만..)

apiVersion은 application compile시 사용한 Vulkan API Header version을 명시합니다. 일반적으로 VK_API_VERSION_1_0 macro를 사용해 1.0.0 (patch level 0)임을 알립니다. (sample이라 patch level를 이용하는 경우는 없군요. 아마도 선행개발시 patch level을 설정해 삽질을 해야할 일이 발생할 수도..)

다시 vkCreateInstance로

이제 웬만한건 다 살펴봤습니다. 하나 VkAllocationCallbacks를 보지 않았네요. 설명에 따르면 host memory management (예를 들면 logging..) 용도 등으로 사용되나 sample에선 NULL을 쓰고 이 경우 default system memory를 사용한다고 합니다. 여기에서 host memory와 default memory의 차이는 뭔지? 하고 궁금할 수 있는데 역시 실사용 예를 보면 바로 이해할 수 있으니 그 때 가서 보죠.

이렇게 해서 vkCreateInstance()를 호출해 VkInstance object을 생성하고 유저는 VkInstance 핸들을 받아옵니다.
일반적인 핸들(handle)과 같이 VkInstance 핸들도 1이상의 정수 입니다.

정리해보죠.

  • VkInstance object는 application의 state를 관리한다.
  • application은 무조건 object를 생성해야 한다. (1개)
  • 변수 type은 Vk~로 함수는 vk~로 시작한다.
  • VkInstance object를 생성하였으면 이제 사용할 graphic device가 뭐가 있고 뭘 쓸지 알아보는 과정이 필요하다.

02 sample은 target (vulkan application이 동작하는 환경)에서 사용할 수 있는 GPU가 뭐가 있는지 찾아보는
과정을 설명합니다.