initial commit
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 25 Oct 2020 14:38:35 +0000 (16:38 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 25 Oct 2020 14:38:35 +0000 (16:38 +0200)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/ggfx_vk.c [new file with mode: 0644]
src/gphgfx.h [new file with mode: 0644]
test.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..0932ecf
--- /dev/null
@@ -0,0 +1,4 @@
+*.o
+*.d
+*.swp
+test
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6060218
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+src = $(wildcard src/*.c) test.c
+obj = $(src:.c=.o)
+dep = $(obj:.o=.d)
+bin = test
+
+CFLAGS = -pedantic -Wall -g -MMD -Isrc
+LDFLAGS = -lvulkan -lm
+
+$(bin): $(obj)
+       $(CC) -o $@ $(obj) $(LDFLAGS)
+
+-include $(dep)
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(bin)
+
+
+.PHONY: cleandep
+cleandep:
+       rm -f $(dep)
diff --git a/src/ggfx_vk.c b/src/ggfx_vk.c
new file mode 100644 (file)
index 0000000..dd8b832
--- /dev/null
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <vulkan/vulkan.h>
+#include "gphgfx.h"
+
+#define VER_MAJOR      0
+#define VER_MINOR      1
+
+static const char *vk_strerror(VkResult res);
+
+static VkInstance vk;
+
+int ggfx_init(const char *appname, unsigned int flags)
+{
+       VkResult res;
+       VkInstanceCreateInfo iinf = {0};
+       VkApplicationInfo appinf = {0};
+       VkLayerProperties *lprop = 0;
+       VkExtensionProperties *iext;
+       uint32_t i, j, num_inst_layers, num_inst_ext, lprop_count, iext_count;
+       char **inst_layers = 0, **inst_ext = 0;
+
+       static const char *debug_layers[] = {
+               "VK_LAYER_LUNARG_device_limits",
+               "VK_LAYER_LUNARG_image",
+               "VK_LAYER_LUNARG_object_tracker",
+               "VK_LAYER_LUNARG_core_validation",
+               "VK_LAYER_LUNARG_parameter_validation",
+               "VK_LAYER_LUNARG_swapchain",
+               "VK_LAYER_GOOGLE_threading",
+               "VK_LAYER_GOOGLE_unique_objects",
+               0
+       };
+       static const char *extensions[] = {
+               "VK_KHR_surface",
+               "VK_KHR_xlib_surface",
+               0
+       };
+
+       vkEnumerateInstanceLayerProperties(&lprop_count, 0);
+       if(lprop_count > 0) {
+               if(!(lprop = malloc(lprop_count * sizeof *lprop))) {
+                       perror("ggfx_init: failed to allocate layer property list");
+                       return -1;
+               }
+               vkEnumerateInstanceLayerProperties(&lprop_count, lprop);
+
+               if(flags & GGFX_INIT_DEBUG) {
+                       if(!(inst_layers = malloc(lprop_count * sizeof *inst_layers))) {
+                               perror("ggfx_init: failed to allocate layer properties");
+                               return -1;
+                       }
+               }
+
+               printf("%d available instance layers\n", lprop_count);
+               num_inst_layers = 0;
+               for(i=0; i<lprop_count; i++) {
+                       char use = ' ';
+                       if(inst_layers) {
+                               for(j=0; debug_layers[j]; j++) {
+                                       if(strcmp(lprop[i].layerName, debug_layers[j]) == 0) {
+                                               inst_layers[num_inst_layers++] = lprop[i].layerName;
+                                               use = '*';
+                                               break;
+                                       }
+                               }
+
+                       }
+                       printf(" [%c] %s: %s\n", use, lprop[i].layerName, lprop[i].description);
+               }
+       }
+
+       vkEnumerateInstanceExtensionProperties(0, &iext_count, 0);
+       if(iext_count > 0) {
+               if(!(iext = malloc(iext_count * sizeof *iext))) {
+                       perror("ggfx_init: failed to allocate instance extensions property list");
+                       return -1;
+               }
+               vkEnumerateInstanceExtensionProperties(0, &iext_count, iext);
+
+               if(!(inst_ext = malloc(iext_count * sizeof *inst_ext))) {
+                       perror("ggfx_init: failed to allocate instance extension properties");
+                       return -1;
+               }
+
+               printf("%d available instance extensions\n", iext_count);
+               num_inst_ext = 0;
+               for(i=0; i<iext_count; i++) {
+                       char use = ' ';
+                       for(j=0; extensions[j]; j++) {
+                               if(strcmp(iext[i].extensionName, extensions[j]) == 0) {
+                                       inst_ext[num_inst_ext++] = iext[i].extensionName;
+                                       use = '*';
+                                       break;
+                               }
+                       }
+                       printf(" [%c] %s\n", use, iext[i].extensionName);
+               }
+       }
+
+
+       appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+       appinf.pApplicationName = appname ? appname : "unknown";
+       appinf.applicationVersion = 1;
+       appinf.pEngineName = "gph-gfx";
+       appinf.engineVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, 0);
+
+       iinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+       iinf.pApplicationInfo = &appinf;
+       iinf.ppEnabledLayerNames = (const char**)inst_layers;
+       iinf.enabledLayerCount = num_inst_layers;
+       iinf.ppEnabledExtensionNames = (const char**)inst_ext;
+       iinf.enabledExtensionCount = num_inst_ext;
+
+       if((res = vkCreateInstance(&iinf, 0, &vk)) != 0) {
+               fprintf(stderr, "ggfx_init: failed to create vulkan instance: %s\n", vk_strerror(res));
+               return -1;
+       }
+
+       return 0;
+}
+
+void ggfx_shutdown(void)
+{
+       if(!vk) return;
+
+       vkDestroyInstance(vk, 0);
+       vk = 0;
+}
+
+static const char *vk_strerror(VkResult res)
+{
+       switch(res) {
+       case VK_SUCCESS: return "success";
+       case VK_NOT_READY: return "not ready";
+       case VK_TIMEOUT: return "timeout";
+       case VK_EVENT_SET: return "event set";
+       case VK_EVENT_RESET: return "event reset";
+       case VK_INCOMPLETE: return "incomplete";
+    case VK_ERROR_OUT_OF_HOST_MEMORY: return "out of host memory";
+    case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "out of device memory";
+    case VK_ERROR_INITIALIZATION_FAILED: return "init failed";
+    case VK_ERROR_DEVICE_LOST: return "device lost";
+    case VK_ERROR_MEMORY_MAP_FAILED: return "map failed";
+    case VK_ERROR_LAYER_NOT_PRESENT: return "layer not present";
+    case VK_ERROR_EXTENSION_NOT_PRESENT: return "extension not present";
+    case VK_ERROR_FEATURE_NOT_PRESENT: return "feature not present";
+    case VK_ERROR_INCOMPATIBLE_DRIVER: return "incompatible driver";
+    case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects";
+    case VK_ERROR_FORMAT_NOT_SUPPORTED: return "format not supported";
+    case VK_ERROR_FRAGMENTED_POOL: return "framgented pool";
+    case VK_ERROR_OUT_OF_POOL_MEMORY: return "out of pool memory";
+    case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "invalid external handle";
+    case VK_ERROR_FRAGMENTATION: return "fragmentation";
+    case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: return "invalid opaque capture address";
+    case VK_ERROR_SURFACE_LOST_KHR: return "surface lost";
+    case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "native window in use";
+    case VK_SUBOPTIMAL_KHR: return "suboptimal";
+    case VK_ERROR_OUT_OF_DATE_KHR: return "out of date";
+    case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "incompatible display";
+    case VK_ERROR_VALIDATION_FAILED_EXT: return "validation failed";
+    case VK_ERROR_INVALID_SHADER_NV: return "invalid shader";
+    case VK_ERROR_INCOMPATIBLE_VERSION_KHR: return "incompatible version";
+    case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "invalid DRM format modifier plane layout";
+    case VK_ERROR_NOT_PERMITTED_EXT: return "not permitted";
+    case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "fullscreen exclusive mode lost";
+    case VK_THREAD_IDLE_KHR: return "thread idle";
+    case VK_THREAD_DONE_KHR: return "thread done";
+    case VK_OPERATION_DEFERRED_KHR: return "operation deferred";
+    case VK_OPERATION_NOT_DEFERRED_KHR: return "operation not deferred";
+    case VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT: return "pipeline compile required";
+
+    case VK_ERROR_UNKNOWN:
+       default:
+               break;
+       }
+
+       return "unknown";
+}
diff --git a/src/gphgfx.h b/src/gphgfx.h
new file mode 100644 (file)
index 0000000..4b90199
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef GPHGFX_H_
+#define GPHGFX_H_
+
+struct ggfx_rend;
+struct ggfx_shader;
+
+enum { GGFX_INIT_DEBUG = 1 };
+
+int ggfx_init(const char *appname, unsigned int flags);
+void ggfx_shutdown(void);
+
+struct ggfx_rend *ggfx_alloc_rend(void);
+void ggfx_free_rend(struct ggfx_rend *rend);
+struct ggfx_rend *ggfx_clone_rend(void);
+
+void ggfx_finalize(struct ggfx_rend *rend);
+void ggfx_enable(struct ggfx_rend *rend, unsigned int s);
+void ggfx_disable(struct ggfx_rend *rend, unsigned int s);
+
+void ggfx_clear_color(struct ggfx_rend *rend, float r, float g, float b, float a);
+void ggfx_clear_depth(struct ggfx_rend *rend, float z);
+void ggfx_clear_stencil(struct ggfx_rend *rend, int s);
+
+void ggfx_set_shader(struct ggfx_rend *rend, int sdrtype, struct ggfx_shader *sdr);
+
+#endif /* GPHGFX_H_ */
diff --git a/test.c b/test.c
new file mode 100644 (file)
index 0000000..8e9395e
--- /dev/null
+++ b/test.c
@@ -0,0 +1,11 @@
+#include "gphgfx.h"
+
+int main(int argc, char **argv)
+{
+       if(ggfx_init("test", GGFX_INIT_DEBUG) == -1) {
+               return 1;
+       }
+
+       ggfx_shutdown();
+       return 0;
+}