Initialisation

Explaining the basics of how to initialise a Vulkan application and the steps required to do so.

As mentioned in General Structure of a Vulkan Application, there is a lot of initialisation that is required before Vulkan can be used in an application. In this application, there are three main stages for initialisation, and each of those stages have their own separate sub-steps. Other applications may take other forms, but Vulkan itself does not impose a grouping of initialisation tasks.

Initialising objects in Vulkan

The process of initialising an application in Vulkan is a significantly longer and more involved process compared to other APIs. Vulkan also does not usually make use of default parameters, therefore all parameters need to be explicitly defined. Tasks such as memory allocation have to be handled by the developer rather than being handled by the driver in the background.

Objects are created and initialised in Vulkan using a VkCreateInfo struct. and a vkCreate function. The actual name and type of the struct and function will vary depending on the object in question. The struct contains details about the object that is going to be created, and can be seen as a "parameters" object. The vkCreate method takes in this struct as as well as a pointer to where the handle will be returned. An example is shown below:

    VkDeviceCreateInfo deviceInfo; // This is the creation struct.
    
    // These are the properties of the object that is going to be created.
    deviceInfo.flags = 0;
    deviceInfo.pNext = nullptr;
    deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    deviceInfo.enabledLayerCount = 0;
    deviceInfo.ppEnabledLayerNames = nullptr;
    deviceInfo.enabledExtensionCount = static_cast<uint32_t>(appManager.deviceExtensionNames.size());
    deviceInfo.ppEnabledExtensionNames = appManager.deviceExtensionNames.data();
    deviceInfo.queueCreateInfoCount = 1;    
    deviceInfo.pQueueCreateInfos = &deviceQueueInfo;
    deviceInfo.pEnabledFeatures = &features;
    
    // This is a vkCreate function.
    // appManager.device is where the object will be stored when created.
    vkCreateDevice(appManager.physicalDevice, &deviceInfo, nullptr, &appManager.device);

Of note here are three specific members that are common to all creation structs:

sType
This is the type of the CreateInfo struct. Usually set with an enum of type VkStructureType.
pNext
This used in the case where a Vulkan extension requires additional information when setting up an object. pNext points to another struct which will contain additional information - this allows the original struct to not need to be aware of the extension. Because this tutorial uses no extensions, this will always be set to null.
flags
This is used to pass additional information. In this case (and throughout this example) this is reserved for future use and is set to zero.

While these three are present in all CreateInfo structs, the rest of the struct will be different depending on what sort of object is being created. Thus, it is not particularly important at this stage to worry about the example shown; it simply highlights the method used in creating an object.