fixed build on windows
[gph-gfx] / src / ggfx_vk.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <vulkan/vulkan.h>
6 #include "gphgfx.h"
7
8 #define VER_MAJOR       0
9 #define VER_MINOR       1
10
11 static const char *vk_strerror(VkResult res);
12
13 static VkInstance vk;
14
15 int ggfx_init(const char *appname, unsigned int flags)
16 {
17         VkResult res;
18         VkInstanceCreateInfo iinf = {0};
19         VkApplicationInfo appinf = {0};
20         VkLayerProperties *lprop = 0;
21         VkExtensionProperties *iext;
22         uint32_t i, j, num_inst_layers, num_inst_ext, lprop_count, iext_count, pdev_count;
23         char **inst_layers = 0, **inst_ext = 0;
24         VkPhysicalDevice *pdev;
25         VkPhysicalDeviceProperties pdevp;
26
27         static const char *debug_layers[] = {
28                 "VK_LAYER_LUNARG_device_limits",
29                 "VK_LAYER_LUNARG_image",
30                 "VK_LAYER_LUNARG_object_tracker",
31                 "VK_LAYER_LUNARG_core_validation",
32                 "VK_LAYER_LUNARG_parameter_validation",
33                 "VK_LAYER_LUNARG_swapchain",
34                 "VK_LAYER_GOOGLE_threading",
35                 "VK_LAYER_GOOGLE_unique_objects",
36                 0
37         };
38         static const char *extensions[] = {
39                 "VK_KHR_surface",
40                 "VK_KHR_xlib_surface",
41                 "VK_KHR_win32_surface",
42                 0
43         };
44
45         vkEnumerateInstanceLayerProperties(&lprop_count, 0);
46         if(lprop_count > 0) {
47                 if(!(lprop = malloc(lprop_count * sizeof *lprop))) {
48                         perror("ggfx_init: failed to allocate layer property list");
49                         return -1;
50                 }
51                 vkEnumerateInstanceLayerProperties(&lprop_count, lprop);
52
53                 if(flags & GGFX_INIT_DEBUG) {
54                         if(!(inst_layers = malloc(lprop_count * sizeof *inst_layers))) {
55                                 perror("ggfx_init: failed to allocate layer properties");
56                                 return -1;
57                         }
58                 }
59
60                 printf("%d available instance layers\n", lprop_count);
61                 num_inst_layers = 0;
62                 for(i=0; i<lprop_count; i++) {
63                         char use = ' ';
64                         if(inst_layers) {
65                                 for(j=0; debug_layers[j]; j++) {
66                                         if(strcmp(lprop[i].layerName, debug_layers[j]) == 0) {
67                                                 inst_layers[num_inst_layers++] = lprop[i].layerName;
68                                                 use = '*';
69                                                 break;
70                                         }
71                                 }
72
73                         }
74                         printf(" [%c] %s: %s\n", use, lprop[i].layerName, lprop[i].description);
75                 }
76         }
77
78         vkEnumerateInstanceExtensionProperties(0, &iext_count, 0);
79         if(iext_count > 0) {
80                 if(!(iext = malloc(iext_count * sizeof *iext))) {
81                         perror("ggfx_init: failed to allocate instance extensions property list");
82                         return -1;
83                 }
84                 vkEnumerateInstanceExtensionProperties(0, &iext_count, iext);
85
86                 if(!(inst_ext = malloc(iext_count * sizeof *inst_ext))) {
87                         perror("ggfx_init: failed to allocate instance extension properties");
88                         return -1;
89                 }
90
91                 printf("%d available instance extensions\n", iext_count);
92                 num_inst_ext = 0;
93                 for(i=0; i<iext_count; i++) {
94                         char use = ' ';
95                         for(j=0; extensions[j]; j++) {
96                                 if(strcmp(iext[i].extensionName, extensions[j]) == 0) {
97                                         inst_ext[num_inst_ext++] = iext[i].extensionName;
98                                         use = '*';
99                                         break;
100                                 }
101                         }
102                         printf(" [%c] %s\n", use, iext[i].extensionName);
103                 }
104         }
105
106
107         appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
108         appinf.pApplicationName = appname ? appname : "unknown";
109         appinf.applicationVersion = 1;
110         appinf.pEngineName = "gph-gfx";
111         appinf.engineVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, 0);
112
113         iinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
114         iinf.pApplicationInfo = &appinf;
115         iinf.ppEnabledLayerNames = (const char**)inst_layers;
116         iinf.enabledLayerCount = num_inst_layers;
117         iinf.ppEnabledExtensionNames = (const char**)inst_ext;
118         iinf.enabledExtensionCount = num_inst_ext;
119
120         if((res = vkCreateInstance(&iinf, 0, &vk)) != 0) {
121                 fprintf(stderr, "ggfx_init: failed to create vulkan instance: %s\n", vk_strerror(res));
122                 return -1;
123         }
124
125         if(vkEnumeratePhysicalDevices(vk, &pdev_count, 0) != 0 || !pdev_count) {
126                 fprintf(stderr, "ggfx_init: failed to enumerate physical devices\n");
127                 return -1;
128         }
129         if(!(pdev = malloc(pdev_count * sizeof *pdev))) {
130                 perror("ggfx_init: failed to allocate memory for physical devices");
131                 return -1;
132         }
133         vkEnumeratePhysicalDevices(vk, &pdev_count, pdev);
134
135         printf("Found %d physical devices\n", pdev_count);
136         for(i=0; i<pdev_count; i++) {
137                 vkGetPhysicalDeviceProperties(pdev[i], &pdevp);
138                 printf(" - %s\n", pdevp.deviceName);
139         }
140
141         return 0;
142 }
143
144 void ggfx_shutdown(void)
145 {
146         if(!vk) return;
147
148         vkDestroyInstance(vk, 0);
149         vk = 0;
150 }
151
152 static const char *vk_strerror(VkResult res)
153 {
154         switch(res) {
155         case VK_SUCCESS: return "success";
156         case VK_NOT_READY: return "not ready";
157         case VK_TIMEOUT: return "timeout";
158         case VK_EVENT_SET: return "event set";
159         case VK_EVENT_RESET: return "event reset";
160         case VK_INCOMPLETE: return "incomplete";
161     case VK_ERROR_OUT_OF_HOST_MEMORY: return "out of host memory";
162     case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "out of device memory";
163     case VK_ERROR_INITIALIZATION_FAILED: return "init failed";
164     case VK_ERROR_DEVICE_LOST: return "device lost";
165     case VK_ERROR_MEMORY_MAP_FAILED: return "map failed";
166     case VK_ERROR_LAYER_NOT_PRESENT: return "layer not present";
167     case VK_ERROR_EXTENSION_NOT_PRESENT: return "extension not present";
168     case VK_ERROR_FEATURE_NOT_PRESENT: return "feature not present";
169     case VK_ERROR_INCOMPATIBLE_DRIVER: return "incompatible driver";
170     case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects";
171     case VK_ERROR_FORMAT_NOT_SUPPORTED: return "format not supported";
172     case VK_ERROR_FRAGMENTED_POOL: return "framgented pool";
173     case VK_ERROR_OUT_OF_POOL_MEMORY: return "out of pool memory";
174     case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "invalid external handle";
175     case VK_ERROR_FRAGMENTATION: return "fragmentation";
176     case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: return "invalid opaque capture address";
177     case VK_ERROR_SURFACE_LOST_KHR: return "surface lost";
178     case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "native window in use";
179     case VK_SUBOPTIMAL_KHR: return "suboptimal";
180     case VK_ERROR_OUT_OF_DATE_KHR: return "out of date";
181     case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "incompatible display";
182     case VK_ERROR_VALIDATION_FAILED_EXT: return "validation failed";
183     case VK_ERROR_INVALID_SHADER_NV: return "invalid shader";
184     case VK_ERROR_INCOMPATIBLE_VERSION_KHR: return "incompatible version";
185     case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "invalid DRM format modifier plane layout";
186     case VK_ERROR_NOT_PERMITTED_EXT: return "not permitted";
187     case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "fullscreen exclusive mode lost";
188     case VK_THREAD_IDLE_KHR: return "thread idle";
189     case VK_THREAD_DONE_KHR: return "thread done";
190     case VK_OPERATION_DEFERRED_KHR: return "operation deferred";
191     case VK_OPERATION_NOT_DEFERRED_KHR: return "operation not deferred";
192     case VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT: return "pipeline compile required";
193
194     case VK_ERROR_UNKNOWN:
195         default:
196                 break;
197         }
198
199         return "unknown";
200 }