4 #include <vulkan/vulkan.h>
9 #include <vulkan/vulkan_win32.h>
11 #include <vulkan/vulkan_xlib.h>
14 static int create_instance(void);
15 static int create_surface(void);
16 static int choose_phys_dev(void);
17 static int create_device(void);
18 static int choose_pixfmt(void);
19 static int eval_pdev_score(VkPhysicalDevice dev);
20 static int have_inst_layer(const char *name);
21 static int have_ext(VkExtensionProperties *ext, int next, const char *name);
27 static VkPhysicalDevice vkpdev;
28 static int vkqfam_idx = -1;
29 static VkDevice vkdev;
31 static VkSurfaceKHR vksurf;
32 static VkSurfaceCapabilitiesKHR vksurf_caps;
33 static int vksurf_numfmt, vksurf_selfmt;
34 static VkSurfaceFormatKHR *vksurf_fmt;
35 static VkSwapchainKHR vksc;
36 static int vksc_numimg;
38 static VkLayerProperties *inst_layers;
39 static VkExtensionProperties *inst_ext, *dev_ext;
40 static uint32_t inst_ext_count, dev_ext_count, inst_layers_count;
42 static VkPhysicalDevice *pdev_list;
43 static uint32_t num_pdev;
45 static int have_raytrace, have_debug_report;
47 void vk_init_xwin(Display *d, Window w)
55 if(create_instance() == -1) return -1;
56 if(create_surface() == -1) return -1;
57 if(choose_phys_dev() == -1) return -1;
58 if(create_device() == -1) return -1;
64 vkDestroyInstance(vk, 0);
71 #define ARRSZ(arr) (sizeof arr / sizeof *arr)
72 static const char *known_layer_list[] = {
73 "VK_LAYER_GOOGLE_threading",
74 "VK_LAYER_LUNARG_parameter_validation",
75 "VK_LAYER_LUNARG_object_tracker",
76 "VK_LAYER_LUNARG_image",
77 "VK_LAYER_LUNARG_core_validation",
78 "VK_LAYER_LUNARG_swapchain",
79 "VK_LAYER_GOOGLE_unique_objects"
85 } known_instext_list[] = {
86 {"VK_KHR_surface", 1},
88 {"VK_KHR_win32_surface", 1},
90 {"VK_KHR_xlib_surface", 1},
92 {"VK_KHR_debug_report", 0}
95 static int create_instance(void)
97 int i, nlayers = 0, next = 0;
98 VkInstanceCreateInfo instinf;
99 VkApplicationInfo appinf;
100 const char *layers[ARRSZ(known_layer_list)];
101 const char *ext[ARRSZ(known_instext_list)];
104 vkEnumerateInstanceVersion(&apiver);
105 printf("Vulkan API version: %d.%d.%d\n", (apiver >> 22) & 0x7f,
106 (apiver >> 12) & 0x3ff, apiver & 0xfff);
108 memset(&appinf, 0, sizeof appinf);
109 appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
110 appinf.pApplicationName = "vkray";
111 appinf.pEngineName = "vkray";
112 appinf.apiVersion = apiver;
114 vkEnumerateInstanceLayerProperties(&inst_layers_count, 0);
115 inst_layers = malloc_nf(inst_layers_count * sizeof *inst_layers);
116 vkEnumerateInstanceLayerProperties(&inst_layers_count, inst_layers);
118 vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, 0);
119 inst_ext = malloc_nf(inst_ext_count * sizeof *inst_ext);
120 vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, inst_ext);
123 for(i=0; i<inst_layers_count; i++) {
124 printf(" - %s: %s\n", inst_layers[i].layerName, inst_layers[i].description);
126 printf("Instance extensions:\n");
127 for(i=0; i<inst_ext_count; i++) {
128 printf(" - %s\n", inst_ext[i].extensionName);
131 have_debug_report = have_ext(inst_ext, inst_ext_count, "VK_KHR_debug_report");
133 for(i=0; i<ARRSZ(known_layer_list); i++) {
134 if(have_inst_layer(known_layer_list[i])) {
135 layers[nlayers++] = known_layer_list[i];
138 for(i=0; i<ARRSZ(known_instext_list); i++) {
139 if(have_ext(inst_ext, inst_ext_count, known_instext_list[i].name)) {
140 ext[next++] = known_instext_list[i].name;
141 } else if(known_instext_list[i].required) {
142 fprintf(stderr, "Vulkan implementation lacks required instance extension: %s\n",
143 known_instext_list[i].name);
148 memset(&instinf, 0, sizeof instinf);
149 instinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
150 instinf.pApplicationInfo = &appinf;
151 instinf.enabledLayerCount = nlayers;
152 instinf.ppEnabledLayerNames = layers;
153 instinf.enabledExtensionCount = next;
154 instinf.ppEnabledExtensionNames = ext;
155 if(vkCreateInstance(&instinf, 0, &vk) != 0) {
156 fprintf(stderr, "failed to create vulkan instance\n");
163 static int create_surface(void)
165 VkXlibSurfaceCreateInfoKHR xinf = {0};
166 xinf.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
170 if(vkCreateXlibSurfaceKHR(vk, &xinf, 0, &vksurf) != 0) {
171 fprintf(stderr, "failed to create Xlib window surface\n");
177 int choose_phys_dev(void)
179 uint32_t i, num_pdev, score, best_score, best_dev;
180 VkPhysicalDevice *pdev;
181 VkPhysicalDeviceProperties pdevprop;
183 vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
185 fprintf(stderr, "no vulkan devices found\n");
188 pdev = malloc_nf(num_pdev * sizeof *pdev);
189 vkEnumeratePhysicalDevices(vk, &num_pdev, pdev);
191 printf("Found %d physical devices\n", num_pdev);
195 for(i=0; i<num_pdev; i++) {
196 if((score = eval_pdev_score(pdev[i])) && score > best_score) {
201 vkGetPhysicalDeviceProperties(pdev[i], &pdevprop);
202 printf(" %d: %s (score: %d)\n", i, pdevprop.deviceName, score);
205 fprintf(stderr, "no suitable vulkan device found\n");
217 static int create_device(void)
222 static int eval_pdev_score(VkPhysicalDevice dev)
224 uint32_t i, num_fmt, num_qfam, num_ext;
225 VkQueueFamilyProperties *qfam;
226 VkExtensionProperties *ext;
227 VkPhysicalDeviceProperties prop;
228 VkPhysicalDeviceFeatures feat;
229 VkSurfaceFormatKHR *sfmt;
232 vkGetPhysicalDeviceProperties(dev, &prop);
233 vkGetPhysicalDeviceFeatures(dev, &feat);
235 /* check if we have the swapchain extension */
236 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, 0);
237 ext = malloc_nf(num_ext * sizeof *ext);
238 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, ext);
240 if(!have_ext(ext, num_ext, "VK_KHR_swapchain")) {
245 /* populate format and present modes arrays, and make sure we have some of each */
246 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, 0);
251 sfmt = malloc_nf(num_fmt * sizeof *sfmt);
252 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, sfmt);
254 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev, vksurf, &vksurf_caps);
256 /* find a queue family which can do graphics and can present */
257 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, 0);
258 qfam = malloc_nf(num_qfam * sizeof *qfam);
259 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, qfam);
262 for(i=0; i<num_qfam; i++) {
263 vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, vksurf, &can_pres);
264 if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) {
279 static int choose_pixfmt(void)
281 static const VkFormat pref[] = {
282 VK_FORMAT_B8G8R8_UNORM,
283 VK_FORMAT_R8G8B8_UNORM,
284 VK_FORMAT_B8G8R8A8_UNORM,
285 VK_FORMAT_R8G8B8A8_UNORM
289 VkSurfaceFormatKHR *sfmt;
291 vkGetPhysicalDeviceSurfaceFormatsKHR(vkpdev, vksurf, &num_fmt, 0);
292 if(!num_fmt) return -1;
293 sfmt = malloc_nf(num_fmt * sizeof *sfmt);
294 vkGetPhysicalDeviceSurfaceFormatsKHR(vkpdev, vksurf, &num_fmt, sfmt);
297 for(i=0; i<num_fmt; i++) {
298 if(sfmt[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
301 for(j=0; j<sizeof pref / sizeof *pref; j++) {
302 if(sfmt[i].format == pref[j]) {
314 static int have_inst_layer(const char *name)
317 for(i=0; i<inst_layers_count; i++) {
318 if(strcmp(inst_layers[i].layerName, name) == 0) {
325 static int have_ext(VkExtensionProperties *ext, int next, const char *name)
328 for(i=0; i<next; i++) {
329 if(strcmp(ext[i].extensionName, name) == 0) {