Scientia Conditorium

[Vulkan][오류] VUID-vkGetDeviceQueue-queueFamilyIndex 오류 본문

프로그래밍/컴퓨터 그래픽스

[Vulkan][오류] VUID-vkGetDeviceQueue-queueFamilyIndex 오류

크썸 2023. 12. 2. 23:57

[Vulkan][오류] VUID-vkGetDeviceQueue-queueFamilyIndex 오류

 

Vulkan 프로그램 초기화하는 도중에 vkGetDeviceQueue 함수에서 에러가 발생하였다.

validation layer: Validation Error: [ VUID-vkGetDeviceQueue-queueFamilyIndex-00384 ] | MessageID = 0x99bbdd45 | vkGetDeviceQueue(): queueFamilyIndex (0) is not one of the queue families given via VkDeviceQueueCreateInfo structures when the device was created. The Vulkan spec states: queueFamilyIndex must be one of the queue family indices specified when device was created, via the VkDeviceQueueCreateInfo structure (https://vulkan.lunarg.com/doc/view/1.3.268.0/windows/1.3-extensions/vkspec.html#VUID-vkGetDeviceQueue-queueFamilyIndex-00384)

validation layer: Validation Error: [ VUID-vkGetDeviceQueue-queueFamilyIndex-00384 ] | MessageID = 0x99bbdd45 | vkGetDeviceQueue(): queueFamilyIndex (0) is not one of the queue families given via VkDeviceQueueCreateInfo structures when the device was created. The Vulkan spec states: queueFamilyIndex must be one of the queue family indices specified when device was created, via the VkDeviceQueueCreateInfo structure (https://vulkan.lunarg.com/doc/view/1.3.268.0/windows/1.3-extensions/vkspec.html#VUID-vkGetDeviceQueue-queueFamilyIndex-00384)

 

vkGetDeivceQueue() 함수에서 queueFamilyIndex(0)가 디바이스 생성 시 VkDeviceQueueCreateInfo 구조체를 통해 지정된 큐 패밀리에 속하지 않았다는 것이다. Vulkan 사양에 따르면 queueFamilyIndex는 디바이스 생성 시 VkDeviceQueueCreateInfo 구조체를 통해 지정된 큐 패밀리의 인덱스 중 하나여야 한다.

 

오류 메시지의 링크를 타고 들어가서 문제의 vkGetDeviceQuque 함수 매개변수를 다시 살펴보도록 하자.

// Provided by VK_VERSION_1_0
void vkGetDeviceQueue(
    VkDevice                                    device,
    uint32_t                                    queueFamilyIndex,
    uint32_t                                    queueIndex,
    VkQueue*                                    pQueue);
  • device : 큐를 소유한 논리적 장치
  • queueFamilyIndex : pQueue가 속해 있는 큐 패밀리의 인덱스
  • queueIndex : 큐 패밀리 내에 (queueFamilyIndex가 가리키는) 검색할 큐 인덱스
  • pQueue는 요청된 큐의 핸들로 채워질 VkQueue 개체에 대한 포인터

오류를 다시 말하자면 queueFamilyIndex(0) 즉, VkDeviceQueueCreateInfo 구조체를 통해 지정된 큐 패밀리 인덱스 값과 두 번째 매개변수인 queueFamilyIndex 값이 0으로 다르다라는 것이다. 이제 코드를 다시 분석해보자.

여기서 나온 오류는 Vulkan tutorial 코드를 따라하다가 발생한 것이다.


 

문제 코드와 수정 코드

QueueFamilyIndices indices = findQueueFamilies(mPhysicalDevice);

std::vector<VkDeviceQueueCreateInfo> queueCreateInfoVector{};
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.has_value(), indices.presentFamily.has_value() };
// 올바른 코드
// std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };

float queuePriority = 1.0f;
for (uint32_t queueFamily : uniqueQueueFamilies)
{
	VkDeviceQueueCreateInfo queueCreateInfo{};
	queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
	queueCreateInfo.queueFamilyIndex = queueFamily; // 여기서 오류 발생
	queueCreateInfo.queueCount = 1;
	queueCreateInfo.pQueuePriorities = &queuePriority;
	queueCreateInfoVector.push_back(queueCreateInfo);
}

// .... 생략

vkGetDeviceQueue(mDevice, indices.graphicsFamily.value(), 0, &mGraphicsQueue);
vkGetDeviceQueue(mDevice, indices.presentFamily.value(), 0, &mPresentQueue);

 

코드를 따라하다가 uniqueQueueFamilies set 컨테이너를 만들 때 실수한 것이다. QueueFamilyIndeces 구조체에 멤버 변수 graphicsFamily와 presentFamily는 각각 optional 클래스 템플릿을 사용하고 있다. 따라서 has_value() 함수를 사용했을 때, 나오는 값은 1이 된다. 그 상태에서 queueCreateInfo.queueFamilyIndex에 값을 집어넣었기 때문에 큐 패밀리 인덱스 값이 1로 설정된 것이다.

마지막 vkGetDeviceQueue에서 indices.graphicsFamily.value() 함수 호출하면 값은 0이된다. 따라서 큐 패밀리 인덱스 값과 매개변수에 넣어줄 인덱스 값이 다르기 때문에 오류가 발생한 것이다. 하드코딩으로 매개변수 값을 1로 바꾸면 오류는 사라지지만 의도한 코드는 아니다.

 

결론적으로 큐 생성할 때 사용한 VkDeviceQueueCreateInfo 구조체에 사용한 queueFamilyIndex과 vkGetDeviceQueue의 queueFamilyIndex 값을 주의하자!