foo
[vkray] / src / vk.c
diff --git a/src/vk.c b/src/vk.c
new file mode 100644 (file)
index 0000000..1fcba58
--- /dev/null
+++ b/src/vk.c
@@ -0,0 +1,189 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <vulkan/vulkan.h>
+#include "vk.h"
+#include "util.h"
+
+static int create_instance(void);
+static int create_device(void);
+static int have_inst_layer(const char *name);
+static int have_inst_ext(const char *name);
+static int have_dev_ext(const char *name);
+
+static VkInstance vk;
+
+static VkLayerProperties *inst_layers;
+static VkExtensionProperties *inst_ext, *dev_ext;
+static uint32_t inst_ext_count, dev_ext_count, inst_layers_count;
+
+static VkPhysicalDevice *pdev_list;
+static uint32_t num_pdev;
+
+static int have_debug_report;
+
+#define ARRSZ(arr)     (sizeof arr / sizeof *arr)
+static const char *known_layer_list[] = {
+       "VK_LAYER_GOOGLE_threading",
+       "VK_LAYER_LUNARG_parameter_validation",
+       "VK_LAYER_LUNARG_object_tracker",
+       "VK_LAYER_LUNARG_image",
+       "VK_LAYER_LUNARG_core_validation",
+       "VK_LAYER_LUNARG_swapchain",
+       "VK_LAYER_GOOGLE_unique_objects"
+};
+
+static struct {
+       const char *name;
+       int required;
+} known_ext_list[] = {
+       {"VK_KHR_surface", 1},
+#ifdef __WIN32__
+       {"VK_KHR_win32_surface", 1},
+#else
+       {"VK_KHR_xlib_surface", 1},
+#endif
+       {"VK_KHR_debug_report", 0},
+       {"VK_KHR_acceleration_structure", 0},
+       {"VK_KHR_ray_tracing_pipeline", 0}
+};
+
+int vk_init(void)
+{
+       if(create_instance() == -1) {
+               return -1;
+       }
+       if(create_device() == -1) {
+               return -1;
+       }
+       return 0;
+}
+
+void vk_cleanup(void)
+{
+       vkDestroyInstance(vk, 0);
+       free(inst_layers);
+       free(inst_ext);
+       free(pdev_list);
+}
+
+
+static int create_instance(void)
+{
+       int i, nlayers = 0, next = 0;
+       VkInstanceCreateInfo instinf;
+       VkApplicationInfo appinf;
+       const char *layers[ARRSZ(known_layer_list)];
+       const char *ext[ARRSZ(known_ext_list)];
+       uint32_t apiver;
+
+       vkEnumerateInstanceVersion(&apiver);
+       printf("Vulkan API version: %d.%d.%d\n", (apiver >> 22) & 0x7f,
+                       (apiver >> 12) & 0x3ff, apiver & 0xfff);
+
+       memset(&appinf, 0, sizeof appinf);
+       appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+       appinf.pApplicationName = "vkray";
+       appinf.pEngineName = "vkray";
+       appinf.apiVersion = apiver;
+
+       vkEnumerateInstanceLayerProperties(&inst_layers_count, 0);
+       inst_layers = malloc_nf(inst_layers_count * sizeof *inst_layers);
+       vkEnumerateInstanceLayerProperties(&inst_layers_count, inst_layers);
+
+       vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, 0);
+       inst_ext = malloc_nf(inst_ext_count * sizeof *inst_ext);
+       vkEnumerateInstanceExtensionProperties(0, &inst_ext_count, inst_ext);
+
+       printf("Layers:\n");
+       for(i=0; i<inst_layers_count; i++) {
+               printf(" - %s: %s\n", inst_layers[i].layerName, inst_layers[i].description);
+       }
+       printf("Instance extensions:\n");
+       for(i=0; i<inst_ext_count; i++) {
+               printf(" - %s\n", inst_ext[i].extensionName);
+       }
+       have_debug_report = have_inst_ext("VK_KHR_debug_report");
+
+       for(i=0; i<ARRSZ(known_layer_list); i++) {
+               if(have_inst_layer(known_layer_list[i])) {
+                       layers[nlayers++] = known_layer_list[i];
+               }
+       }
+       for(i=0; i<ARRSZ(known_ext_list); i++) {
+               if(have_inst_ext(known_ext_list[i].name)) {
+                       ext[next++] = known_ext_list[i].name;
+               } else if(known_ext_list[i].required) {
+                       fprintf(stderr, "Vulkan implementation lacks required instance extension: %s\n",
+                                       known_ext_list[i].name);
+                       return -1;
+               }
+       }
+
+       memset(&instinf, 0, sizeof instinf);
+       instinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+       instinf.pApplicationInfo = &appinf;
+       instinf.enabledLayerCount = nlayers;
+       instinf.ppEnabledLayerNames = layers;
+       instinf.enabledExtensionCount = next;
+       instinf.ppEnabledExtensionNames = ext;
+       if(vkCreateInstance(&instinf, 0, &vk) != 0) {
+               fprintf(stderr, "failed to create vulkan instance\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int create_device(void)
+{
+       int i;
+       VkPhysicalDeviceProperties2 pdevprop2;
+       VkPhysicalDeviceAccelerationStructurePropertiesKHR rayacc_prop;
+
+       vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
+       pdev_list = malloc_nf(num_pdev * sizeof *pdev_list);
+       vkEnumeratePhysicalDevices(vk, &num_pdev, pdev_list);
+
+       printf("Found %d physical devices\n", num_pdev);
+       for(i=0; i<num_pdev; i++) {
+               memset(&rayacc_prop, 0, sizeof rayacc_prop);
+               rayacc_prop.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
+
+               memset(&pdevprop2, 0, sizeof pdevprop2);
+               pdevprop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+               pdevprop2.pNext = &rayacc_prop;
+
+               vkGetPhysicalDeviceProperties2(pdev_list[i], &pdevprop2);
+               printf(" %d: %s\n", i, pdevprop2.properties.deviceName);
+       }
+
+       return 0;
+}
+
+static int have_inst_layer(const char *name)
+{
+       int i;
+       for(i=0; i<inst_layers_count; i++) {
+               if(strcmp(inst_layers[i].layerName, name) == 0) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int have_inst_ext(const char *name)
+{
+       int i;
+       for(i=0; i<inst_ext_count; i++) {
+               if(strcmp(inst_ext[i].extensionName, name) == 0) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int have_dev_ext(const char *name)
+{
+       return 0;       /* TODO */
+}