From 977157a1eea893545e7a1c7b8c0a3e6e20dced41 Mon Sep 17 00:00:00 2001 From: Jordan Halase Date: Mon, 4 Nov 2019 10:08:26 -0600 Subject: Parse command line arguments --- main.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 15 deletions(-) diff --git a/main.c b/main.c index 46f381b..0976ef1 100755 --- a/main.c +++ b/main.c @@ -60,6 +60,41 @@ PERFORMANCE OF THIS SOFTWARE. #define APP_THREAD_LOCAL __declspec(thread) #endif +struct Arguments { + bool validation; +}; + +static void printUsage(const char *cmd, struct Arguments *args, bool error) +{ + FILE *fp = error ? stderr : stdout; + const char *const defaultStr = "\t[default]\n"; + const char *const newline = "\n"; + fprintf(fp, "Usage: %s [OPTION...]\n", cmd); + fprintf(fp, " -h, --help\t\tShow this help message\n"); + fprintf(fp, " --validation\t\tRun with Vulkan validation layers and debug callback%s", + args->validation ? defaultStr : newline); + fprintf(fp, " --no-validation\tRun without Vulkan validation layers or debug callback%s", + !args->validation ? defaultStr : newline); + exit(error); +} + +static void parseArgs(int argc, char **argv, struct Arguments *args) +{ + if (argc < 2) { + return; + } + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { + printUsage(argv[0], args, false); + } else if (!strcmp(argv[1], "--validation")) { + args->validation = true; + } else if (!strcmp(argv[1], "--no-validation")) { + args->validation = false; + } else { + fprintf(stderr, "Unknown option `%s`\n", argv[1]); + printUsage(argv[0], args, true); + } +} + /** Vulkan allocation callbacks if we ever decide to use them when debugging. * * This is put in a macro so we don't have to look for every Vulkan function @@ -71,6 +106,9 @@ PERFORMANCE OF THIS SOFTWARE. struct VulkanAPI { void *handle; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; PFN_vkCreateInstance vkCreateInstance; PFN_vkDestroyInstance vkDestroyInstance; PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; @@ -447,17 +485,8 @@ static void rvkDestroyInternalInstance(struct RenderVulkan *vk) * If errors occurred, the struct will be returned in an unusable state. * It MUST then be destroyed via `rvkDestroyWorld`. * */ -int rvkCreateWorld(struct RenderVulkan **vkOut) +int rvkCreateWorld(struct RenderVulkan **vkOut, bool validation) { - static const char *const instanceLayers[] = { - "VK_LAYER_KHRONOS_validation" - }; - const uint32_t nInstanceLayers = sizeof(instanceLayers) / sizeof(instanceLayers[0]); - static const char *const instanceExtensions[] = { - VK_EXT_DEBUG_REPORT_EXTENSION_NAME - }; - const uint32_t nInstanceExtensions = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]); - struct RenderVulkan *vk = calloc(1, sizeof(*vk)); *vkOut = vk; vk->world = puglNewWorld(); @@ -479,6 +508,24 @@ int rvkCreateWorld(struct RenderVulkan **vkOut) return -1; } + vk->api->vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vk->api->vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); + if (!vk->api->vkEnumerateInstanceVersion) { + rvkSetErrMsg(vk, "Error loading `vkEnumerateInstanceVersion`"); + return -1; + } + + vk->api->vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)vk->api->vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); + if (!vk->api->vkEnumerateInstanceExtensionProperties) { + rvkSetErrMsg(vk, "Error loading `vkEnumerateInstanceExtensionProperties`"); + return -1; + } + + vk->api->vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties)vk->api->vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceLayerProperties"); + if (!vk->api->vkEnumerateInstanceLayerProperties) { + rvkSetErrMsg(vk, "Error loading `vkEnumerateInstanceLayerProperties`"); + return -1; + } + vk->api->vkCreateInstance = (PFN_vkCreateInstance)vk->api->vkGetInstanceProcAddr(NULL, "vkCreateInstance"); if (!vk->api->vkCreateInstance) { rvkSetErrMsg(vk, "Error loading `vkCreateInstance`"); @@ -488,9 +535,26 @@ int rvkCreateWorld(struct RenderVulkan **vkOut) VkResult result; // FIXME: Use `vkEnumerateInstanceExtensionProperties` to query for // debug & validation support or it will fail if not found. - //if ((result = rvkCreateInternalInstance(vk, 0, NULL, 0, NULL))) { - if ((result = rvkCreateInternalInstance(vk, nInstanceLayers, instanceLayers, nInstanceExtensions, instanceExtensions))) { - return -1; + if (validation) { + static const char *const instanceLayers[] = { + "VK_LAYER_KHRONOS_validation" + }; + const uint32_t nInstanceLayers = sizeof(instanceLayers) / sizeof(instanceLayers[0]); + static const char *const instanceExtensions[] = { + VK_EXT_DEBUG_REPORT_EXTENSION_NAME + }; + const uint32_t nInstanceExtensions = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]); + if ((result = rvkCreateInternalInstance(vk, + nInstanceLayers, + instanceLayers, + nInstanceExtensions, + instanceExtensions))) { + return -1; + } + } else { + if ((result = rvkCreateInternalInstance(vk, 0, NULL, 0, NULL))) { + return -1; + } } static const char *const strErrLd = "Error loading instance function %s"; @@ -1647,15 +1711,25 @@ PuglStatus onEvent(PuglView *view, const PuglEvent *e) return PUGL_SUCCESS; } -int main() +int main(int argc, char **argv) { #if defined(__linux__) /* The Mesa Vulkan drivers require this to be called */ XInitThreads(); #endif + + struct Arguments args = { 0 }; + args.validation = true; + parseArgs(argc, argv, &args); + if (args.validation) { + printf("Using Vulkan validation layers and debug callback\n"); + } else { + printf("Not using Vulkan validation layers or debug callback\n"); + } + /* Vulkan application that uses Pugl for windows and events */ struct RenderVulkan *vk; - CHECK_RVK(vk, rvkCreateWorld(&vk)); + CHECK_RVK(vk, rvkCreateWorld(&vk, args.validation)); printf("Created Vulkan Instance Successfully\n"); -- cgit v1.2.1