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