foo
[vkray] / src / vk.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdint.h>
4 #include <vulkan/vulkan.h>
5 #include "vk.h"
6 #include "util.h"
7
8 static int create_instance(void);
9 static int create_device(void);
10 static int have_inst_layer(const char *name);
11 static int have_inst_ext(const char *name);
12 static int have_dev_ext(const char *name);
13
14 static VkInstance vk;
15
16 static VkLayerProperties *inst_layers;
17 static VkExtensionProperties *inst_ext, *dev_ext;
18 static uint32_t inst_ext_count, dev_ext_count, inst_layers_count;
19
20 static VkPhysicalDevice *pdev_list;
21 static uint32_t num_pdev;
22
23 static int have_debug_report;
24
25 #define ARRSZ(arr)      (sizeof arr / sizeof *arr)
26 static const char *known_layer_list[] = {
27         "VK_LAYER_GOOGLE_threading",
28         "VK_LAYER_LUNARG_parameter_validation",
29         "VK_LAYER_LUNARG_object_tracker",
30         "VK_LAYER_LUNARG_image",
31         "VK_LAYER_LUNARG_core_validation",
32         "VK_LAYER_LUNARG_swapchain",
33         "VK_LAYER_GOOGLE_unique_objects"
34 };
35
36 static struct {
37         const char *name;
38         int required;
39 } known_ext_list[] = {
40         {"VK_KHR_surface", 1},
41 #ifdef __WIN32__
42         {"VK_KHR_win32_surface", 1},
43 #else
44         {"VK_KHR_xlib_surface", 1},
45 #endif
46         {"VK_KHR_debug_report", 0},
47         {"VK_KHR_acceleration_structure", 0},
48         {"VK_KHR_ray_tracing_pipeline", 0}
49 };
50
51 int vk_init(void)
52 {
53         if(create_instance() == -1) {
54                 return -1;
55         }
56         if(create_device() == -1) {
57                 return -1;
58         }
59         return 0;
60 }
61
62 void vk_cleanup(void)
63 {
64         vkDestroyInstance(vk, 0);
65         free(inst_layers);
66         free(inst_ext);
67         free(pdev_list);
68 }
69
70
71 static int create_instance(void)
72 {
73         int i, nlayers = 0, next = 0;
74         VkInstanceCreateInfo instinf;
75         VkApplicationInfo appinf;
76         const char *layers[ARRSZ(known_layer_list)];
77         const char *ext[ARRSZ(known_ext_list)];
78         uint32_t apiver;
79
80         vkEnumerateInstanceVersion(&apiver);
81         printf("Vulkan API version: %d.%d.%d\n", (apiver >> 22) & 0x7f,
82                         (apiver >> 12) & 0x3ff, apiver & 0xfff);
83
84         memset(&appinf, 0, sizeof appinf);
85         appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
86         appinf.pApplicationName = "vkray";
87         appinf.pEngineName = "vkray";
88         appinf.apiVersion = apiver;
89
90         vkEnumerateInstanceLayerProperties(&inst_layers_count, 0);
91         inst_layers = malloc_nf(inst_layers_count * sizeof *inst_layers);
92         vkEnumerateInstanceLayerProperties(&inst_layers_count, inst_layers);
93
94         vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, 0);
95         inst_ext = malloc_nf(inst_ext_count * sizeof *inst_ext);
96         vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, inst_ext);
97
98         printf("Layers:\n");
99         for(i=0; i<inst_layers_count; i++) {
100                 printf(" - %s: %s\n", inst_layers[i].layerName, inst_layers[i].description);
101         }
102         printf("Instance extensions:\n");
103         for(i=0; i<inst_ext_count; i++) {
104                 printf(" - %s\n", inst_ext[i].extensionName);
105         }
106         have_debug_report = have_inst_ext("VK_KHR_debug_report");
107
108         for(i=0; i<ARRSZ(known_layer_list); i++) {
109                 if(have_inst_layer(known_layer_list[i])) {
110                         layers[nlayers++] = known_layer_list[i];
111                 }
112         }
113         for(i=0; i<ARRSZ(known_ext_list); i++) {
114                 if(have_inst_ext(known_ext_list[i].name)) {
115                         ext[next++] = known_ext_list[i].name;
116                 } else if(known_ext_list[i].required) {
117                         fprintf(stderr, "Vulkan implementation lacks required instance extension: %s\n",
118                                         known_ext_list[i].name);
119                         return -1;
120                 }
121         }
122
123         memset(&instinf, 0, sizeof instinf);
124         instinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
125         instinf.pApplicationInfo = &appinf;
126         instinf.enabledLayerCount = nlayers;
127         instinf.ppEnabledLayerNames = layers;
128         instinf.enabledExtensionCount = next;
129         instinf.ppEnabledExtensionNames = ext;
130         if(vkCreateInstance(&instinf, 0, &vk) != 0) {
131                 fprintf(stderr, "failed to create vulkan instance\n");
132                 return -1;
133         }
134
135         return 0;
136 }
137
138 static int create_device(void)
139 {
140         int i;
141         VkPhysicalDeviceProperties2 pdevprop2;
142         VkPhysicalDeviceAccelerationStructurePropertiesKHR rayacc_prop;
143
144         vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
145         pdev_list = malloc_nf(num_pdev * sizeof *pdev_list);
146         vkEnumeratePhysicalDevices(vk, &num_pdev, pdev_list);
147
148         printf("Found %d physical devices\n", num_pdev);
149         for(i=0; i<num_pdev; i++) {
150                 memset(&rayacc_prop, 0, sizeof rayacc_prop);
151                 rayacc_prop.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
152
153                 memset(&pdevprop2, 0, sizeof pdevprop2);
154                 pdevprop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
155                 pdevprop2.pNext = &rayacc_prop;
156
157                 vkGetPhysicalDeviceProperties2(pdev_list[i], &pdevprop2);
158                 printf(" %d: %s\n", i, pdevprop2.properties.deviceName);
159         }
160
161         return 0;
162 }
163
164 static int have_inst_layer(const char *name)
165 {
166         int i;
167         for(i=0; i<inst_layers_count; i++) {
168                 if(strcmp(inst_layers[i].layerName, name) == 0) {
169                         return 1;
170                 }
171         }
172         return 0;
173 }
174
175 static int have_inst_ext(const char *name)
176 {
177         int i;
178         for(i=0; i<inst_ext_count; i++) {
179                 if(strcmp(inst_ext[i].extensionName, name) == 0) {
180                         return 1;
181                 }
182         }
183         return 0;
184 }
185
186 static int have_dev_ext(const char *name)
187 {
188         return 0;       /* TODO */
189 }