4 #include <vulkan/vulkan.h>
9 #include <vulkan/vulkan_win32.h>
11 /*#include <vulkan/vulkan_xlib.h>*/
12 #include <X11/Xlib-xcb.h>
13 #include <vulkan/vulkan_xcb.h>
16 static int create_instance(void);
17 static int create_surface(void);
18 static int choose_phys_dev(void);
19 static int create_device(void);
20 static int choose_pixfmt(void);
21 static int eval_pdev_score(VkPhysicalDevice dev);
22 static int have_inst_layer(const char *name);
23 static int have_ext(VkExtensionProperties *ext, int next, const char *name);
29 static VkPhysicalDevice vkpdev;
30 static int vkqfam_idx = -1;
31 static VkDevice vkdev;
33 static VkSurfaceKHR vksurf;
34 static VkSurfaceCapabilitiesKHR vksurf_caps;
35 static int vksurf_numfmt, vksurf_selfmt;
36 static VkSurfaceFormatKHR *vksurf_fmt;
37 static VkSwapchainKHR vksc;
38 static int vksc_numimg;
40 static VkLayerProperties *inst_layers;
41 static VkExtensionProperties *inst_ext, *dev_ext;
42 static uint32_t inst_ext_count, dev_ext_count, inst_layers_count;
44 static VkPhysicalDevice *pdev_list;
45 static uint32_t num_pdev;
47 static int have_raytrace, have_debug_report;
49 void vk_init_xwin(Display *d, Window w)
57 if(create_instance() == -1) return -1;
58 if(create_surface() == -1) return -1;
59 if(choose_phys_dev() == -1) return -1;
60 if(create_device() == -1) return -1;
66 vkDestroyInstance(vk, 0);
73 #define ARRSZ(arr) (sizeof arr / sizeof *arr)
74 static const char *known_layer_list[] = {
75 "VK_LAYER_GOOGLE_threading",
76 "VK_LAYER_LUNARG_parameter_validation",
77 "VK_LAYER_LUNARG_object_tracker",
78 "VK_LAYER_LUNARG_image",
79 "VK_LAYER_LUNARG_core_validation",
80 "VK_LAYER_LUNARG_swapchain",
81 "VK_LAYER_GOOGLE_unique_objects"
87 } known_instext_list[] = {
88 {"VK_KHR_surface", 1},
90 {"VK_KHR_win32_surface", 1},
92 /*{"VK_KHR_xlib_surface", 1},*/
93 {"VK_KHR_xcb_surface", 1},
95 {"VK_KHR_debug_report", 0}
98 static int create_instance(void)
100 int i, nlayers = 0, next = 0;
101 VkInstanceCreateInfo instinf;
102 VkApplicationInfo appinf;
103 const char *layers[ARRSZ(known_layer_list)];
104 const char *ext[ARRSZ(known_instext_list)];
107 vkEnumerateInstanceVersion(&apiver);
108 printf("Vulkan API version: %d.%d.%d\n", (apiver >> 22) & 0x7f,
109 (apiver >> 12) & 0x3ff, apiver & 0xfff);
111 memset(&appinf, 0, sizeof appinf);
112 appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
113 appinf.pApplicationName = "vkray";
114 appinf.pEngineName = "vkray";
115 appinf.apiVersion = apiver;
117 vkEnumerateInstanceLayerProperties(&inst_layers_count, 0);
118 inst_layers = malloc_nf(inst_layers_count * sizeof *inst_layers);
119 vkEnumerateInstanceLayerProperties(&inst_layers_count, inst_layers);
121 vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, 0);
122 inst_ext = malloc_nf(inst_ext_count * sizeof *inst_ext);
123 vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, inst_ext);
126 for(i=0; i<inst_layers_count; i++) {
127 printf(" - %s: %s\n", inst_layers[i].layerName, inst_layers[i].description);
129 printf("Instance extensions:\n");
130 for(i=0; i<inst_ext_count; i++) {
131 printf(" - %s\n", inst_ext[i].extensionName);
134 have_debug_report = have_ext(inst_ext, inst_ext_count, "VK_KHR_debug_report");
136 for(i=0; i<ARRSZ(known_layer_list); i++) {
137 if(have_inst_layer(known_layer_list[i])) {
138 layers[nlayers++] = known_layer_list[i];
141 for(i=0; i<ARRSZ(known_instext_list); i++) {
142 if(have_ext(inst_ext, inst_ext_count, known_instext_list[i].name)) {
143 ext[next++] = known_instext_list[i].name;
144 } else if(known_instext_list[i].required) {
145 fprintf(stderr, "Vulkan implementation lacks required instance extension: %s\n",
146 known_instext_list[i].name);
151 memset(&instinf, 0, sizeof instinf);
152 instinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
153 instinf.pApplicationInfo = &appinf;
154 instinf.enabledLayerCount = nlayers;
155 instinf.ppEnabledLayerNames = layers;
156 instinf.enabledExtensionCount = next;
157 instinf.ppEnabledExtensionNames = ext;
158 if(vkCreateInstance(&instinf, 0, &vk) != 0) {
159 fprintf(stderr, "failed to create vulkan instance\n");
166 static int create_surface(void)
171 VkXlibSurfaceCreateInfoKHR xinf = {0};
172 xinf.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
176 if(vkCreateXlibSurfaceKHR(vk, &xinf, 0, &vksurf) != 0) {
177 fprintf(stderr, "failed to create Xlib window surface\n");
181 VkXcbSurfaceCreateInfoKHR xinf = {0};
182 xinf.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
183 xinf.connection = XGetXCBConnection(dpy);
184 xinf.window = (xcb_window_t)win;
186 if((res = vkCreateXcbSurfaceKHR(vk, &xinf, 0, &vksurf)) != 0) {
187 fprintf(stderr, "failed to create XCB window surface (%d)\n", res);
193 int choose_phys_dev(void)
195 uint32_t i, num_pdev, score, best_score, best_dev;
196 VkPhysicalDevice *pdev;
197 VkPhysicalDeviceProperties pdevprop;
199 vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
201 fprintf(stderr, "no vulkan devices found\n");
204 pdev = malloc_nf(num_pdev * sizeof *pdev);
205 vkEnumeratePhysicalDevices(vk, &num_pdev, pdev);
207 printf("Found %d physical devices\n", num_pdev);
211 for(i=0; i<num_pdev; i++) {
212 if((score = eval_pdev_score(pdev[i])) && score > best_score) {
217 vkGetPhysicalDeviceProperties(pdev[i], &pdevprop);
218 printf(" %d: %s (score: %d)\n", i, pdevprop.deviceName, score);
221 fprintf(stderr, "no suitable vulkan device found\n");
233 static int create_device(void)
238 static int eval_pdev_score(VkPhysicalDevice dev)
240 uint32_t i, num_fmt, num_qfam, num_ext;
241 VkQueueFamilyProperties *qfam;
242 VkExtensionProperties *ext;
243 VkPhysicalDeviceProperties prop;
244 VkPhysicalDeviceFeatures feat;
245 VkSurfaceFormatKHR *sfmt;
248 vkGetPhysicalDeviceProperties(dev, &prop);
249 vkGetPhysicalDeviceFeatures(dev, &feat);
251 /* check if we have the swapchain extension */
252 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, 0);
253 ext = malloc_nf(num_ext * sizeof *ext);
254 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, ext);
256 if(!have_ext(ext, num_ext, "VK_KHR_swapchain")) {
261 /* populate format and present modes arrays, and make sure we have some of each */
262 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, 0);
267 sfmt = malloc_nf(num_fmt * sizeof *sfmt);
268 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, sfmt);
270 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev, vksurf, &vksurf_caps);
272 /* find a queue family which can do graphics and can present */
273 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, 0);
274 qfam = malloc_nf(num_qfam * sizeof *qfam);
275 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, qfam);
278 for(i=0; i<num_qfam; i++) {
279 vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, vksurf, &can_pres);
280 if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) {
295 static int choose_pixfmt(void)
297 static const VkFormat pref[] = {
298 VK_FORMAT_B8G8R8_UNORM,
299 VK_FORMAT_R8G8B8_UNORM,
300 VK_FORMAT_B8G8R8A8_UNORM,
301 VK_FORMAT_R8G8B8A8_UNORM
305 VkSurfaceFormatKHR *sfmt;
307 vkGetPhysicalDeviceSurfaceFormatsKHR(vkpdev, vksurf, &num_fmt, 0);
308 if(!num_fmt) return -1;
309 sfmt = malloc_nf(num_fmt * sizeof *sfmt);
310 vkGetPhysicalDeviceSurfaceFormatsKHR(vkpdev, vksurf, &num_fmt, sfmt);
313 for(i=0; i<num_fmt; i++) {
314 if(sfmt[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
317 for(j=0; j<sizeof pref / sizeof *pref; j++) {
318 if(sfmt[i].format == pref[j]) {
330 static int have_inst_layer(const char *name)
333 for(i=0; i<inst_layers_count; i++) {
334 if(strcmp(inst_layers[i].layerName, name) == 0) {
341 static int have_ext(VkExtensionProperties *ext, int next, const char *name)
344 for(i=0; i<next; i++) {
345 if(strcmp(ext[i].extensionName, name) == 0) {