Get Start Vulkan






Vulkan promises to be next level API to make and see 'oh those wonderous worlds', and with an edge on performance . Know more about Vulkan here

There are a few samples to start within the SDK and here

The samples have a few classes/types abstracted and can be daunting for beginners so here's a step by step

1. Ensure you have the latest vulkan drivers for your GPU. This will install some dlls for the ICD.
2. Download the Windows SDK
3. Have Visual Studio /VC ++ Express installed and running. I compiled on VS 2010
4. Create a new Win32 C++ console project
5. Add a new main.cpp with the following code:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <Windows.h>
#include <vulkan.h>
#include <conio.h>
#include <stdio.h>
#include <vector>

#define APP_SHORT_NAME "Vulkan01"
uint8_t idx = -1;
int main(){
	
	/**
	Steps required
	1. Create Vulkan Instance 
	2. Enumerate the GPUs
	3. Query Queues on the GPU (Queues probably represent 'channels' on which the data shall process?, query the queue
		for COMPUTE type queue or GRAPHICS type queue
	4. Create a queue priority
	5. Create a device with information from 2, 3 and 4
	**/
	
	/** 1. Create Vulkan Instance **/
	VkApplicationInfo appInfo = {};
	
	appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
	appInfo.pNext = NULL;
	appInfo.pApplicationName = APP_SHORT_NAME;
	appInfo.applicationVersion = 1;
	appInfo.pEngineName = APP_SHORT_NAME;
	appInfo.engineVersion = 1;
	appInfo.apiVersion = VK_API_VERSION;

	VkInstanceCreateInfo icInfo = {};
	icInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
	icInfo.pNext = NULL;
	icInfo.flags = 0;
	icInfo.pApplicationInfo = & appInfo;
	icInfo.enabledExtensionCount = 0;
	icInfo.ppEnabledExtensionNames = NULL;
	icInfo.enabledLayerCount = 0;
	icInfo.enabledLayerCount = NULL;

	VkInstance instance;
	VkResult res;

	res = vkCreateInstance(&icInfo, NULL, &instance);
	if(res == VK_ERROR_INCOMPATIBLE_DRIVER){
		printf("Cannot find a Vulkan Compatible ICD\n");
		exit(-1);
	} else if(res){
		printf("Some error occured\n");
		exit(-1);
	}
	printf("Yay! Vulkan is initialized\n");

	/** 2. Enumerate the GPUs **/
	uint32_t gpuCount = 0;
	
	res = vkEnumeratePhysicalDevices(instance, &gpuCount, NULL);
	printf("found %d gpus\n", gpuCount);
	VkPhysicalDevice* gpus = new VkPhysicalDevice[gpuCount];

	printf("Listing gpus...\n", gpuCount);
	res = vkEnumeratePhysicalDevices(instance, &gpuCount, gpus);
	
	while(++idx < gpuCount){
		VkPhysicalDeviceProperties props= {};
		vkGetPhysicalDeviceProperties(gpus[idx], &props);
		printf("%d-%d-%d-%d-%s\n", props.apiVersion, props.driverVersion, props.vendorID, props.deviceID, props.deviceName);
	}

	
	/** 3. Query for the supported queues **/
	uint32_t queue_count = 0;
	vkGetPhysicalDeviceQueueFamilyProperties(gpus[0], &queue_count, NULL);
	if(queue_count <= 0){
		printf("No Queues found.. aborting\n");
		exit(-1);
	}

	VkQueueFamilyProperties* queue_props = new VkQueueFamilyProperties[queue_count];

	vkGetPhysicalDeviceQueueFamilyProperties(gpus[0], &queue_count, queue_props);

	float queue_priorities[1] = {0.0};		/** 4. Create a queue priority **/
	VkDeviceQueueCreateInfo qi = {};
	qi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
	qi.pNext = NULL;
	qi.queueCount = 1;
	qi.pQueuePriorities = queue_priorities;

	idx = -1;
	while(++idx < queue_count){
		if(queue_props[idx].queueFlags & VK_QUEUE_GRAPHICS_BIT){
			qi.queueFamilyIndex = idx;				
			break;
		}
	}

	/** 5. Create a device with information from 2, 3 and 4 **/
	
	VkDeviceCreateInfo dci = {};
	dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	dci.pNext = NULL;
	dci.queueCreateInfoCount = 1;
	dci.pQueueCreateInfos = &qi;
	dci.enabledExtensionCount = 0;
	dci.ppEnabledExtensionNames = NULL;
	dci.enabledLayerCount = 0;
	dci.ppEnabledLayerNames = NULL;
	dci.pEnabledFeatures = NULL;

	VkDevice device;
	res = vkCreateDevice(gpus[0], &dci, NULL, &device);
	if(res){
		printf("There was a problem creating the device");
		exit(-1);
	}
	vkDestroyDevice(device, NULL);
	printf("Device created");
	vkDestroyInstance(instance, NULL);
	
	delete[] gpus;

	return 0;
}


6. Now on to linking to the correct libraries. The static library (vulkan-1.lib) should be linked from $(VK_SDK_PATH)\Source\lib32 or lib (for 64 bit systems). Please bear in mind that if you link against the vulkan-1.lib in  $(VK_SDK_PATH)\Bin\ , you might encounter the familiar LNK2019: Unresolved External Symbol linking error.

7. Compile and Run and one should be able to see details of their gpu on screen

Github download


Comments

Popular Posts