edc3bf1650a53af71ffedf4496e259047c41ed35
[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_raytrace, 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
107         have_raytrace = have_inst_ext("VK_KHR_ray_tracing_pipeline");
108         have_debug_report = have_inst_ext("VK_KHR_debug_report");
109
110         for(i=0; i<ARRSZ(known_layer_list); i++) {
111                 if(have_inst_layer(known_layer_list[i])) {
112                         layers[nlayers++] = known_layer_list[i];
113                 }
114         }
115         for(i=0; i<ARRSZ(known_ext_list); i++) {
116                 if(have_inst_ext(known_ext_list[i].name)) {
117                         ext[next++] = known_ext_list[i].name;
118                 } else if(known_ext_list[i].required) {
119                         fprintf(stderr, "Vulkan implementation lacks required instance extension: %s\n",
120                                         known_ext_list[i].name);
121                         return -1;
122                 }
123         }
124
125         memset(&instinf, 0, sizeof instinf);
126         instinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
127         instinf.pApplicationInfo = &appinf;
128         instinf.enabledLayerCount = nlayers;
129         instinf.ppEnabledLayerNames = layers;
130         instinf.enabledExtensionCount = next;
131         instinf.ppEnabledExtensionNames = ext;
132         if(vkCreateInstance(&instinf, 0, &vk) != 0) {
133                 fprintf(stderr, "failed to create vulkan instance\n");
134                 return -1;
135         }
136
137         return 0;
138 }
139
140 static int create_device(void)
141 {
142         int i;
143         VkPhysicalDeviceProperties2 pdevprop2;
144         VkPhysicalDeviceRayTracingPipelinePropertiesKHR raypipe_prop;
145         VkPhysicalDeviceAccelerationStructurePropertiesKHR rayacc_prop;
146
147         vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
148         pdev_list = malloc_nf(num_pdev * sizeof *pdev_list);
149         vkEnumeratePhysicalDevices(vk, &num_pdev, pdev_list);
150
151         printf("Found %d physical devices\n", num_pdev);
152         for(i=0; i<num_pdev; i++) {
153                 if(have_raytrace) {
154                         memset(&rayacc_prop, 0, sizeof rayacc_prop);
155                         rayacc_prop.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
156
157                         memset(&raypipe_prop, 0, sizeof raypipe_prop);
158                         raypipe_prop.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
159                         raypipe_prop.pNext = &rayacc_prop;
160                 }
161
162                 memset(&pdevprop2, 0, sizeof pdevprop2);
163                 pdevprop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
164                 pdevprop2.pNext = have_raytrace ? &raypipe_prop : 0;
165
166                 vkGetPhysicalDeviceProperties2(pdev_list[i], &pdevprop2);
167                 printf(" %d: %s\n", i, pdevprop2.properties.deviceName);
168                 if(have_raytrace) {
169                         printf("  Raytracing properties:\n");
170                         printf("    max ray recursion: %u\n", raypipe_prop.maxRayRecursionDepth);
171                         printf("    max ray dispatch: %u\n", raypipe_prop.maxRayDispatchInvocationCount);
172                         printf("    max leaf geometry: %llu\n", (unsigned long long)rayacc_prop.maxGeometryCount);
173                         printf("    max leaf primitves: %llu\n", (unsigned long long)rayacc_prop.maxPrimitiveCount);
174                         printf("    max instances: %llu\n", (unsigned long long)rayacc_prop.maxInstanceCount);
175                 }
176         }
177
178         return 0;
179 }
180
181 static int have_inst_layer(const char *name)
182 {
183         int i;
184         for(i=0; i<inst_layers_count; i++) {
185                 if(strcmp(inst_layers[i].layerName, name) == 0) {
186                         return 1;
187                 }
188         }
189         return 0;
190 }
191
192 static int have_inst_ext(const char *name)
193 {
194         int i;
195         for(i=0; i<inst_ext_count; i++) {
196                 if(strcmp(inst_ext[i].extensionName, name) == 0) {
197                         return 1;
198                 }
199         }
200         return 0;
201 }
202
203 static int have_dev_ext(const char *name)
204 {
205         return 0;       /* TODO */
206 }