1 #define GLFW_INCLUDE_VULKAN
2 #include <GLFW/glfw3.h>
13 /* global variables */
14 extern GLFWwindow *win;
18 /* static variables */
19 static std::vector<std::string> enabled_extension_names;
20 static VkInstance inst;
21 static VkDevice device;
22 static VkPhysicalDevice pdev;
23 static VkSurfaceKHR surface;
24 static uint32_t device_mem_idx;
25 static uint32_t num_queues;
26 static uint32_t qfamily_idx;
28 static const char *print_vulkan_error(VkResult error);
29 static const char *dev_type_str(VkPhysicalDeviceType type);
30 static const char *heap_flags_str(VkMemoryHeapFlags flags);
31 static const char *memtype_flags_str(VkMemoryPropertyFlags flags);
32 static const char *queue_flags_str(VkQueueFlags flags);
34 /* static fumctions */
35 static bool create_instance();
36 static bool create_device();
41 fprintf(stderr, "Failed to initialize GLFW.\n");
45 if(!glfwVulkanSupported()) {
46 fprintf(stderr, "No Vulkan support on the device.\n");
50 if(!create_instance()) {
51 fprintf(stderr, "Failed to enable validation.\n");
55 if(!glfwGetPhysicalDevicePresentationSupport(inst, pdev, qfamily_idx)) {
56 fprintf(stderr, "Presentation support not found.\n");
60 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
61 if(!(win = glfwCreateWindow(win_w, win_h, "vkcow", 0, 0))) {
62 fprintf(stderr, "Failed to create window.\n");
66 if(VkResult err = glfwCreateWindowSurface(inst, win, 0, &surface)) {
67 fprintf(stderr, "Failed to create KHR surface: %s\n", print_vulkan_error(err));
76 //TODOs according to the book:
77 // 1- make sure all threads have been terminated (when I add threads)
78 // 2- destroy objects in *reverse* order
80 vkDestroySurfaceKHR(inst, surface, 0);
82 if(vkDeviceWaitIdle(device) == VK_SUCCESS) {
83 vkDestroyDevice(device, 0);
84 vkDestroyInstance(inst, 0);
88 static bool create_instance()
91 uint32_t layer_count = 0;
92 std::vector<const char *> enabled_layers;
94 if(vkEnumerateInstanceLayerProperties(&layer_count, 0) != VK_SUCCESS) {
95 fprintf(stderr, "Failed to query layer properties.\n");
100 VkLayerProperties *layers = (VkLayerProperties *)alloca(layer_count * sizeof *layers);
101 vkEnumerateInstanceLayerProperties(&layer_count, layers);
102 for(uint32_t i=0; i<layer_count; i++) {
103 if(strcmp(layers[i].layerName, "VK_LAYER_LUNARG_standard_validation")) {
104 enabled_layers.push_back(layers[i].layerName);
109 /* enable extensions */
110 uint32_t extensions_count = 0;
111 std::vector<const char *> enabled_extensions;
113 if(vkEnumerateInstanceExtensionProperties(0, &extensions_count, 0) != VK_SUCCESS) {
114 fprintf(stderr, "Failed to enumerate instance extension properties\n");
118 if(extensions_count > 0) {
119 VkExtensionProperties *extensions = (VkExtensionProperties *)alloca(extensions_count * sizeof *extensions);
120 vkEnumerateInstanceExtensionProperties(0, &extensions_count, extensions);
122 for(uint32_t i=0; i<extensions_count; i++) {
123 printf("Extension %u: %s %u.\n", i, extensions[i].extensionName, extensions[i].specVersion);
124 //enable all the available extensions
125 enabled_extensions.push_back(extensions[i].extensionName);
126 enabled_extension_names.push_back(std::string(extensions[i].extensionName));
130 /* create instance */
131 VkInstanceCreateInfo create_info;
132 memset(&create_info, 0, sizeof create_info);
133 create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
135 if(!enabled_layers.empty()) {
136 create_info.enabledLayerCount = enabled_layers.size();
137 create_info.ppEnabledLayerNames = enabled_layers.data();
140 if(!enabled_extensions.empty()) {
141 create_info.enabledExtensionCount = enabled_extensions.size();
142 create_info.ppEnabledExtensionNames = enabled_extensions.data();
145 if(vkCreateInstance(&create_info, 0, &inst) != VK_SUCCESS) {
146 fprintf(stderr, "Failed to create instance.\n");
156 static bool create_device()
162 if(vkEnumeratePhysicalDevices(inst, &dev_count, 0) != VK_SUCCESS) {
163 fprintf(stderr, "Failed to enumerate physical devices.\n");
166 printf("%u devices found.\n", (unsigned int)dev_count);
168 VkPhysicalDevice *phys_dev = (VkPhysicalDevice *)alloca(dev_count * sizeof *phys_dev);
169 vkEnumeratePhysicalDevices(inst, &dev_count, phys_dev);
170 VkPhysicalDeviceMemoryProperties memprop;
172 for(uint32_t i=0; i<dev_count; i++) {
173 VkPhysicalDeviceProperties dev_props;
174 vkGetPhysicalDeviceProperties(phys_dev[i], &dev_props);
177 vkGetPhysicalDeviceMemoryProperties(phys_dev[i], &memprop);
178 printf("\tNumber of heaps: %u\n", memprop.memoryHeapCount);
179 for(uint32_t j=0; j<memprop.memoryHeapCount; j++) {
180 printf("\t\tHeap %u size: %lu\n", j, (unsigned long)memprop.memoryHeaps[j].size);
181 printf("\t\tHeap %u flags: %s\n", j, heap_flags_str(memprop.memoryHeaps[j].flags));
184 printf("\tMemory types: %u\n", memprop.memoryTypeCount);
185 for(uint32_t j=0; j<memprop.memoryTypeCount; j++) {
186 printf("\t\tType %u heap index: %u\n", j, memprop.memoryTypes[j].heapIndex);
187 printf("\t\tType %u flags: %s\n", j, memtype_flags_str(memprop.memoryTypes[j].propertyFlags));
191 VkPhysicalDeviceFeatures features;
192 vkGetPhysicalDeviceFeatures(phys_dev[i], &features);
196 vkGetPhysicalDeviceQueueFamilyProperties(phys_dev[i], &qfam_count, 0);
197 printf("\tQueue Families: %u\n", qfam_count);
198 VkQueueFamilyProperties *qfam_props = new VkQueueFamilyProperties[qfam_count];
199 vkGetPhysicalDeviceQueueFamilyProperties(phys_dev[i], &qfam_count, qfam_props);
200 for(uint32_t j=0; j<qfam_count; j++) {
201 printf("\t\tFamily %u flags: %s\n", j, queue_flags_str(qfam_props[j].queueFlags));
202 printf("\t\tFamily %u number of queues: %u\n", j, qfam_props[j].queueCount);
204 if((qfam_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) && (pdev_idx == -1)) {
207 num_queues = qfam_props[j].queueCount;
210 delete [] qfam_props;
214 fprintf(stderr, "No suitable devices found.\n");
218 pdev = *(phys_dev + pdev_idx);
219 qfamily_idx = qfam_idx;
221 /* uint32_t layer_count;
222 if(vkEnumerateDeviceLayerProperties(pdev, &layer_count, 0) != VK_SUCCESS) {
223 fprintf(stderr, "Failed to enumerate device layers.\n");
226 if(layer_count > 0) {
227 VkLayerProperties *layers = (VkLayerProperties*)alloca(layer_count * sizeof *layers);
228 vkEnumerateDeviceLayerProperties(pdev, &layer_count, layers);
229 printf("%u layers found.\n", layer_count);
230 for(uint32_t i=0; i<layer_count; i++) {
231 printf("Layer %u: %s (%u, %u)\n", i, layers[i].layerName,
232 layers[i].specVersion, layers[i].implementationVersion);
233 printf("\tDesc: %s\n", layers[i].description);
237 VkDeviceCreateInfo dev_info;
238 memset(&dev_info, 0, sizeof dev_info);
239 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
241 VkDeviceQueueCreateInfo dev_qinfo;
242 memset(&dev_qinfo, 0, sizeof dev_qinfo);
243 dev_qinfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
244 dev_qinfo.queueFamilyIndex = qfam_idx;
245 dev_qinfo.queueCount = 1;
247 dev_info.queueCreateInfoCount = 1;
248 dev_info.pQueueCreateInfos = &dev_qinfo;
250 if(vkCreateDevice(pdev, &dev_info, 0, &device) != VK_SUCCESS) {
251 fprintf(stderr, "Failed to create logical device.\n");
255 vkGetPhysicalDeviceMemoryProperties(pdev, &memprop);
256 for(uint32_t j=0; j<memprop.memoryTypeCount; j++) {
257 if(memprop.memoryTypes[j].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
259 printf("Selected device memory index: %u\n", device_mem_idx);
267 static const char *print_vulkan_error(VkResult error)
272 errmsg = std::string("VK_SUCCESS");
275 errmsg = std::string("VK_NOT_READY");
278 errmsg = std::string("VK_TIMEOUT");
281 errmsg = std::string("VK_EVENT_SET");
284 errmsg = std::string("VK_EVENT_RESET");
287 errmsg = std::string("VK_EVENT");
289 case VK_ERROR_OUT_OF_HOST_MEMORY:
290 errmsg = std::string("VK_ERROR_OUT_OF_HOST_MEMORY");
292 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
293 errmsg = std::string("VK_ERROR_OUT_OF_DEVICE_MEMORY");
295 case VK_ERROR_INITIALIZATION_FAILED:
296 errmsg = std::string("VK_ERROR_INITIALIZATION_FAILED");
298 case VK_ERROR_DEVICE_LOST:
299 errmsg = std::string("VK_ERROR_DEVICE_LOST");
301 case VK_ERROR_MEMORY_MAP_FAILED:
302 errmsg = std::string("VK_ERROR_MEMORY_MAP_FAILED");
304 case VK_ERROR_LAYER_NOT_PRESENT:
305 errmsg = std::string("VK_ERROR_LAYER_NOT_PRESENT");
307 case VK_ERROR_EXTENSION_NOT_PRESENT:
308 errmsg = std::string("VK_ERROR_EXTENSION_NOT_PRESENT");
310 case VK_ERROR_FEATURE_NOT_PRESENT:
311 errmsg = std::string("VK_ERROR_FEATURE_NOT_PRESENT");
313 case VK_ERROR_INCOMPATIBLE_DRIVER:
314 errmsg = std::string("VK_ERROR_INCOMPATIBLE_DRIVER");
316 case VK_ERROR_TOO_MANY_OBJECTS:
317 errmsg = std::string("VK_ERROR_TOO_MANY_OBJECTS");
319 case VK_ERROR_FORMAT_NOT_SUPPORTED:
320 errmsg = std::string("VK_ERROR_FORMAT_NOT_SUPPORTED");
322 case VK_ERROR_FRAGMENTED_POOL:
323 errmsg = std::string("VK_ERROR_FRAGMENTED_POOL");
326 errmsg = std::string("UNKNOWN");
330 return errmsg.c_str();
333 static const char *dev_type_str(VkPhysicalDeviceType type)
336 case VK_PHYSICAL_DEVICE_TYPE_OTHER:
338 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
339 return "integrated GPU";
340 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
341 return "discrete GPU";
342 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
343 return "virtual GPU";
344 case VK_PHYSICAL_DEVICE_TYPE_CPU:
352 static const char *heap_flags_str(VkMemoryHeapFlags flags)
354 static std::string str;
356 if(flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
357 str += "device-local ";
364 static const char *memtype_flags_str(VkMemoryPropertyFlags flags)
366 static std::string str;
368 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
369 str += "device-local ";
371 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
372 str += "host-visible ";
374 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
375 str += "host-coherent ";
377 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
378 str += "host-cached ";
380 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
381 str += "lazily-allocated ";
388 static const char *queue_flags_str(VkQueueFlags flags)
390 static std::string str;
392 if(flags & VK_QUEUE_GRAPHICS_BIT)
394 if(flags & VK_QUEUE_COMPUTE_BIT)
396 if(flags & VK_QUEUE_TRANSFER_BIT)
398 if(flags & VK_QUEUE_SPARSE_BINDING_BIT)
399 str += "sparse-binding ";