[vk] Drawing triangle - setup - Logical device and queue

2021. 8. 6. 04:37그래픽스/vk

1. Logical device and queues

- physical device를 선택한 후, Logical device를 설정한 후 인터페이스 시켜야함

- Logical device 생성 프로세스는 instance 생성 프로세스와 유사하고, 사용하려는 기능을 명시해야한다.

- 또한 사용할 수 있는 queue families를 알게되었으니 실제로 생성할 queue families를 명시해야함.

- multiple logical devices을 같은 physical device에서 만들 수 있다. (다양한 요구사항이 있는 경우)

 

다음은 새로운 클래스 멤버로, logical device를 핸들한다.

VkDevice device;

createLogicalDevice 함수를 추가하고, initVulkan 밑에 추가해야한다.

void initVulkan() {
    createInstance();
    setupDebugMessenger();
    pickPhysicalDevice();
    createLogicalDevice();
}

void createLogicalDevice() {

}

 

 

 

2. Specifying the queues to be created

- 논리적 장치를 생성하려면 구조체에 여러 세부사항을 다시 지정해야함.

- 첫번째로 createinfo :  VkDeviceQueueCreateInfo

- 이 구조체는 queues의 개수를 기술한다. (single queue family에서)

- 지금은 graphics 기능이 있는 queue 에만 집중한다.

QueueFamilyIndices indices = findQueueFamilies(physicalDevice);

VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
queueCreateInfo.queueCount = 1;

- currently available drivers : 오직 작은수의 queues만 생성하도록 허용함.

- 실제로는 둘이상은 필요없음

- 여러 스레드에서 모든 command buffer 를 만든 다음 약간의 작은 overhead call로 

- 주 스레드에 한번에 모두 건네줄 수 있기 때문이다.

- Vulkan은 queues에 0.0과 1.0 사이의 floating point number로 우선순위를 할당하여

- command buffer의 스케쥴링에 영향을 줄 수 있다.

- 큐가 하나뿐이라도 필수적임.

float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;

 

 

 

3. Specifying used device features

- 다음은 사용해야할  the set of device features 를 명시해야한다.

- vkGetPhysicalDeviceFeatures 를 통해 얻은 features 을 명시해야한다는것

- 지금 당장은 특별히 아무것도 할게 없으므로 VK_FALSE로 설정해줘야한다.

 (sampler Anisotropy등을 명시하여 특정 기능을 사용할 수 있음)

- 이런 기능을 사용하려면 physical device feature

VkPhysicalDeviceFeatures deviceFeatures{};

 

 

 

 

4. Creating the logical device

- 이제 만들어진 두개의 구조체를 VkDeviceCreateInfo 로 전달해야한다.

 

VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

- 먼저 device features structs 를 pointers 에 전달.

createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;

createInfo.pEnabledFeatures = &deviceFeatures;

- 나머지는 VkInstanceCreateInfo 와 유사하게 구조체 멤버변수를 명시한다.

- 필요한 extensions 과 validation layers를 명시해야한다는것.

- 차이점은 이번에는 divece specific 이라는점이다.

- - device specific extension ex) VK_KHR_swapchain 
- - 렌더할 이미지를 device에서 window로 나타내게해줌  하지만
- - vulkan devices이 system에서 이러한 기능이 부족할 수 있다.
- - 예를 들어 오직 compute operations 만 지원하는 device일 수 있다는것

 

Vulkan은 이전에 instance 와 device specific validation layers 를 구분했지만 더이상그렇지않음.

- 이것은 두 fild 변수가 이제 필요없음을 의미함. enabledLayerCount, ppEnabledLayerNames

- 따라서 최신버전에선 이전 버전과의 호환을위해 다음과 같이 설정해줘야한다,

- 또한 현재 device specific extensions은 쓰지 않으니 0으로 설정한것을 볼 수 있음.

createInfo.enabledExtensionCount = 0;

if (enableValidationLayers) {
    createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
    createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
    createInfo.enabledLayerCount = 0;
}

 

vkCreateDevice

- 이제 logical device를 인스턴스화(instantiate) 할 준비가 다 되었으니 vkCreateDevice 함수를 호출만하면된다.

if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
    throw std::runtime_error("failed to create logical device!");
}

 

- 매개변수 1 : the physical device to interface with,

- 매개변수 2 : queue와 feature 등 사용정보가 담긴 create info

- 매개변수 3 : optional allocation pointer

- 매개변수 4 : 생성할 logical device 의 주소값

- 항상 create 하면 생성이 잘되어있는지 확인하는게 필요하다.

- ex) 존재하지 않은 확장을 활성화 or 지원이 되지 않는 feature 등등

 

vkDestroyDevice

void cleanup() {
    vkDestroyDevice(device, nullptr);
    ...
}

- 함께 device 와 destroy 됨.

- Logical devices 은  instances에 직접 상호작용하지 않으므로, 매개변수에 포함안되는 것을 볼수 있음.

 

 

 

 

5. Retrieving queue handles

- 큐는 logical device와 함께 자동으로 생성되지만, 인터페이스할 핸들이 없음

- 먼저 그래픽 queue 에 대한 핸들을 저장할 클래스 멤버를 추가해야함.

VkQueue graphicsQueue;

- device queues 은 device가 파괴될때 암시적으로 정리되므로 cleanup에 따로 명시안해줘도 됨.

 

vkGetDeviceQueue

vkGetDeviceQueue

- 이 함수를 사용하여 각 queue family에 대한 queue handle을 검색할 수 있음

// Provided by VK_VERSION_1_0
void vkGetDeviceQueue(
    VkDevice                                    device,
    uint32_t                                    queueFamilyIndex,
    uint32_t                                    queueIndex,
    VkQueue*                                    pQueue);
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);

- 매개변수 1 : 논리적 장치 - queue를 소유한 논리적 장치

- 매개변수 2 : queue family index - queue 가 속한 family의 인덱스

- 매개변수 3 : queue의 index - family 안에서의 인덱스.  -> 단일 queue를 생성 하므로 0으로 

- 매개변수 4 : 요청된 queue에 대한 핸들로 채워질 VKQueue 객체에 대한 포인터

 

- logical device, queue handles를 사용하면, 실제로 그래픽 카드를 사용하여 작업을 시작할 수 있다.

- 다음 챕터들은 윈도우 시스템에 결과물을 보여줄 리소스를 설정함.

 

C++ 코드