travisvroman / kohi

A game engine made as part of the Kohi Game Engine series on YouTube (and Twitch!), where we make a game engine from the ground up using C and Vulkan.

Home Page:https://kohiengine.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Validation Error: VkDeviceCreateInfo-queueFamilyIndex-02802

ShadowwLol opened this issue · comments

Bug:

In certain graphics cards, the current queue selection process will pick the same queueFamilyIndex more than once if there are not enough individual queueFamilyIndex's for each (graphics, transfer and present) queue. This triggers a validation error within vulkan that goes as follows:

Output:

Validation Error: [ VUID-VkDeviceCreateInfo-queueFamilyIndex-02802 ] Object 0: handle = 0x1088d50, type = VK_OBJECT_TYPE_PHYSICAL_DEVICE; | MessageID = 0x29498778 | CreateDevice(): pCreateInfo->pQueueCreateInfos[2].queueFamilyIndex (=1) is not unique and was also used in pCreateInfo->pQueueCreateInfos[1]. The Vulkan spec states: The queueFamilyIndex member of each element of pQueueCreateInfos must be unique within pQueueCreateInfos, except that two members can share the same queueFamilyIndex if one describes protected-capable queues and one describes queues that are not protected-capable (https://vulkan.lunarg.com/doc/view/1.3.224.0/linux/1.3-extensions/vkspec.html#VUID-VkDeviceCreateInfo-queueFamilyIndex-02802)

neofetch --stdout

shadoww@xddz 
------------ 
OS: Debian GNU/Linux 11 (bullseye) x86_64 
Host: Aspire A315-21G V1.12 
Kernel: 5.10.0-18-amd64 
Uptime: 1 day, 13 hours, 37 mins 
Packages: 2926 (dpkg) 
Shell: zsh 5.8 
Resolution: 1366x768 
WM: bspwm 
Theme: Adwaita-One-Dark [GTK2/3] 
Icons: hicolor [GTK2/3] 
Terminal: alacritty 
Terminal Font: Iosevka 
CPU: AMD A9-9420 RADEON R5 2C+3G (2) @ 3.000GHz 
GPU: AMD ATI Radeon R5 M230 / R7 M260DX / Radeon 520 Mobile 
GPU: AMD ATI Radeon R2/R3/R4/R5 Graphics 
Memory: 5397MiB / 7410MiB 

VkQueueFamilyProperties (vulkaninfo):

VkQueueFamilyProperties:
========================
	queueProperties[0]:
	-------------------
		minImageTransferGranularity = (1,1,1)
		queueCount                  = 1
		queueFlags                  = QUEUE_GRAPHICS | QUEUE_COMPUTE | QUEUE_TRANSFER | QUEUE_SPARSE_BINDING
		timestampValidBits          = 64
		present support             = true

	queueProperties[1]:
	-------------------
		minImageTransferGranularity = (1,1,1)
		queueCount                  = 4
		queueFlags                  = QUEUE_COMPUTE | QUEUE_TRANSFER | QUEUE_SPARSE_BINDING
		timestampValidBits          = 64
		present support             = true


./engine/src/renderer/vulkan/vulkan_device.c

    if (!transfer_shares_graphics_queue) {
        indices[index++] = context->device.transfer_queue_index;
    }

    VkDeviceQueueCreateInfo queue_create_infos[index_count];
    for (u32 i = 0; i < index_count; ++i) {
        queue_create_infos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queue_create_infos[i].queueFamilyIndex = indices[i];
        queue_create_infos[i].queueCount = 1;

        // TODO: Enable this for a future enhancement.
        // if (indices[i] == context->device.graphics_queue_index) {
        //     queue_create_infos[i].queueCount = 2;
        // }
        queue_create_infos[i].flags = 0;
        queue_create_infos[i].pNext = 0;
        f32 queue_priority = 1.0f;
        queue_create_infos[i].pQueuePriorities = &queue_priority;
    }

    // Request device features.
    // TODO: should be config driven
    VkPhysicalDeviceFeatures device_features = {};

As you can see above, I've only got 2 "queue families", yet, the current code requires at least one queue family for each mode (graphics, present, transfer).

i think this answer might be too late but this will probably help somebody else
im pretty sure the issue has something to do with queueCreateInfoCount because when using index_count it crashes but when i just set it to 1 it works

    const b8 present_shares_graphics_queue  = context->device.graphics_queue_index == context->device.present_queue_index;
    const b8 transfer_shares_graphics_queue = context->device.graphics_queue_index == context->device.transfer_queue_index;
    uint32_t index_count                    = 1;
    if (!present_shares_graphics_queue) index_count++;
    if (!transfer_shares_graphics_queue) index_count++;

    int32_t indices[index_count];
    uint8_t index            = 0;
    indices[index++]         = context->device.graphics_queue_index;

    if (!present_shares_graphics_queue)
            indices[index++] = context->device.present_queue_index;

    if (!transfer_shares_graphics_queue)
            indices[index++] = context->device.transfer_queue_index;

    VkDeviceQueueCreateInfo pQueueInfo[index_count];

    for (uint32_t i = 0; i < index_count; i++) {
            pQueueInfo[i].sType              = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
            pQueueInfo[i].queueFamilyIndex   = indices[i];
            pQueueInfo[i].queueCount         = 1;
            if (indices[i] == context->device.graphics_queue_index)
                    pQueueInfo[i].queueCount = 1;

            pQueueInfo[i].flags              = 0;
            pQueueInfo[i].pNext              = NULL;
            float queue_priority             = 1.0f;
            pQueueInfo[i].pQueuePriorities   = &queue_priority;
    }

    VkPhysicalDeviceFeatures deviceFeatures;
    s_zerofill(&deviceFeatures, sizeof(deviceFeatures));
    deviceFeatures.samplerAnisotropy = VK_TRUE;

    VkDeviceCreateInfo deviceInfo;
    s_zerofill(&deviceInfo, sizeof(deviceInfo));
    deviceInfo.sType                   = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    deviceInfo.queueCreateInfoCount    = 1;
    deviceInfo.pQueueCreateInfos       = pQueueInfo;
    deviceInfo.pEnabledFeatures        = &deviceFeatures;
    deviceInfo.enabledExtensionCount   = 1;
    const char *extension_names        = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
    deviceInfo.ppEnabledExtensionNames = &extension_names;
    deviceInfo.enabledLayerCount       = 0;
    deviceInfo.ppEnabledLayerNames     = NULL;