summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Halase <jordan@halase.me>2019-10-30 11:46:26 -0500
committerJordan Halase <jordan@halase.me>2019-10-30 11:46:26 -0500
commitd73a1c763f36e1560efc2536f8219784a32a617d (patch)
tree0421aff5d3dfce938a37830d8867c34221cb7b09
parentd9c15249e6a92fe92f741610b9fdb0c8d012e722 (diff)
Overhaul
-rw-r--r--main.c79
1 files changed, 51 insertions, 28 deletions
diff --git a/main.c b/main.c
index dde113a..fb81e89 100644
--- a/main.c
+++ b/main.c
@@ -128,9 +128,10 @@ void *appDlopen(const char *soname)
char *appDlerror()
{
+ // TODO: Print a more informative string. Error codes are annoying.
DWORD errCode = GetLastError();
static APP_THREAD_LOCAL char errStr[64];
- stbsp_sprintf(errStr, "Dynamic Library Error: %d", errCode);
+ stbsp_snprintf(errStr, sizeof(errStr), "Dynamic Library Error: %d", errCode);
return errStr;
}
@@ -145,22 +146,22 @@ int appDlclose(void *handle)
return FreeLibrary(handle);
}
-void getRequiredInstanceExtensions(void *windowCtx,
- unsigned *nRequired,
- const char **const extensions)
+void getRequiredInstanceExtensions(PuglWorld *world,
+ unsigned *pExtensionCount,
+ const char **const ppExtensionNames)
{
- (void)windowCtx;
+ (void)world;
static const char *const required[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_WIN32_SURFACE_EXTENSION_NAME
};
static const unsigned num = sizeof(required) / sizeof(required[0]);
- if (extensions) {
+ if (ppExtensionNames) {
for (int i = 0; i < num; ++i) {
- extensions[i] = required[i];
+ ppExtensionNames[i] = required[i];
}
} else {
- *nRequired = num;
+ *pExtensionCount = num;
}
}
@@ -205,27 +206,38 @@ int appDlclose(void *handle)
}
/* XXX: puglGetRequiredInstanceExtensions()
+ * This will return the platform-specific names of the instance level
+ * extensions required to display images to the screen.
+ * Vulkan is off-screen by default and can be used without presenting
+ * at all, so off-screen applications will not need to call this
+ * function. In other words:
+ *
+ * "Get the names of the required instance extensions if you want to
+ * display your images to the screen."
+ *
* TODO: Linux actually has three possible surfaces: Xlib, XCB, and Wayland.
* This should be figured out at runtime (without using #ifdefs).
- * In which case, `windowCtx` will be used to determine which to use.
- * As of now, Pugl (and LV2!) only supports Xlib.
+ * In which case, `world` will be used to determine which to use.
+ * As of now, Pugl (and LV2! suil, etc.) only supports Xlib, but the
+ * variable should be left in the function signature for forward
+ * compatibility.
*/
-void getRequiredInstanceExtensions(void *windowCtx,
- unsigned *nRequired,
- const char **const extensions)
+void getRequiredInstanceExtensions(PuglWorld *world,
+ unsigned *pExtensionCount,
+ const char **const ppExtensionNames)
{
- (void)windowCtx;
+ (void)world;
static const char *const required[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_XLIB_SURFACE_EXTENSION_NAME
};
static const unsigned num = sizeof(required) / sizeof(required[0]);
- if (extensions) {
+ if (ppExtensionNames) {
for (int i = 0; i < num; ++i) {
- extensions[i] = required[i];
+ ppExtensionNames[i] = required[i];
}
} else {
- *nRequired = num;
+ *pExtensionCount = num;
}
}
@@ -406,7 +418,6 @@ struct RenderVulkan *rvkCreate()
return vk;
}
- /* TODO: This could perhaps be generated */
static const char *const strErrLd = "Error loading function %s";
static const char *const strDestroyInstance = "vkDestroyInstance";
@@ -417,7 +428,7 @@ struct RenderVulkan *rvkCreate()
return vk;
}
- /* It is okay if debug reporter functions are not resolved */
+ /* It is okay if debug reporter functions are not resolved (for now) */
uintptr_t *ulCreateDebugReportCallbackEXT = (uintptr_t*)&vk->api->vkCreateDebugReportCallbackEXT;
*ulCreateDebugReportCallbackEXT = (uintptr_t)vk->api->vkGetInstanceProcAddr(vk->instance, "vkCreateDebugReportCallbackEXT");
@@ -430,6 +441,12 @@ struct RenderVulkan *rvkCreate()
return vk;
}
+ /* Dynamically load instance-level Vulkan function pointers via `vkGetInstanceProcAddr`
+ *
+ * TODO: This could perhaps be generated by a script and put into a separate "loader" file
+ *
+ * Casts to `uintptr_t` as an intermediary to suppress warnings when compiling with `-Wpedantic`
+ */
static const char *const strDestroySurfaceKHR = "vkDestroySurfaceKHR";
uintptr_t *ulDestroySurfaceKHR = (uintptr_t*)&vk->api->vkDestroySurfaceKHR;
*ulDestroySurfaceKHR = (uintptr_t)vk->api->vkGetInstanceProcAddr(vk->instance, strDestroySurfaceKHR);
@@ -485,6 +502,7 @@ struct RenderVulkan *rvkCreate()
rvkSetErrMsg(vk, strErrLd, strEnumerateDeviceExtensionProperties);
return vk;
}
+ /* End loading function pointers */
if (vk->api->vkCreateDebugReportCallbackEXT) {
VkDebugReportCallbackCreateInfoEXT debugInfo = { 0 };
@@ -511,6 +529,8 @@ static void rvkCreateSurface(struct RenderVulkan *vk, PuglView *view)
/** Checks if a particular physical device is suitable for this application.
*
+ * This function is referentially transparent.
+ *
* Choosing a physical device is an *extremely* application-specific procedure.
*
* All rendering in Vulkan is done off-screen by default. To get rendered
@@ -544,8 +564,9 @@ static void rvkCreateSurface(struct RenderVulkan *vk, PuglView *view)
* must retrieve queues per-thread.
*
* GOTCHA: Some devices may have multiple GRAPHICS queue families
- * with only one of them able to present. Do not assume a device is
- * unsuitable until ALL queue families have been checked.
+ * with only one of them able to present. Do not assume a
+ * device is unsuitable until ALL queue families have been
+ * checked.
*
* Because this application will load all resources before any rendering begins,
* and the amount of resources are small enough to be loaded almost instantly,
@@ -557,13 +578,13 @@ static void rvkCreateSurface(struct RenderVulkan *vk, PuglView *view)
* https://vulkan.gpuinfo.org/
*/
static int isDeviceSuitable(const struct RenderVulkan *const vk,
- const VkPhysicalDevice pd,
+ const VkPhysicalDevice physicalDevice,
uint32_t *const graphicsIndex)
{
uint32_t nQueueFamilies;
- vk->api->vkGetPhysicalDeviceQueueFamilyProperties(pd, &nQueueFamilies, NULL);
+ vk->api->vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &nQueueFamilies, NULL);
VkQueueFamilyProperties *queueProperties = malloc(nQueueFamilies * sizeof(*queueProperties));
- vk->api->vkGetPhysicalDeviceQueueFamilyProperties(pd, &nQueueFamilies, queueProperties);
+ vk->api->vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &nQueueFamilies, queueProperties);
for (uint32_t i = 0; i < nQueueFamilies; ++i) {
printf("Queue Family %d queueCount:\t%d\n", i, queueProperties[i].queueCount);
}
@@ -571,7 +592,7 @@ static int isDeviceSuitable(const struct RenderVulkan *const vk,
for (g = 0; g < nQueueFamilies; ++g) {
if (queueProperties[g].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
VkBool32 canSurface;
- vk->api->vkGetPhysicalDeviceSurfaceSupportKHR(pd, g, vk->surface, &canSurface);
+ vk->api->vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, g, vk->surface, &canSurface);
if (canSurface) break;
}
}
@@ -583,9 +604,9 @@ static int isDeviceSuitable(const struct RenderVulkan *const vk,
}
VkBool32 canSwapchain = 0;
uint32_t nExtensions;
- vk->api->vkEnumerateDeviceExtensionProperties(pd, NULL, &nExtensions, NULL);
+ vk->api->vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &nExtensions, NULL);
VkExtensionProperties *availableExtensions = malloc(nExtensions * sizeof(*availableExtensions));
- vk->api->vkEnumerateDeviceExtensionProperties(pd, NULL, &nExtensions, availableExtensions);
+ vk->api->vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &nExtensions, availableExtensions);
for (uint32_t i = 0; i < nExtensions; ++i) {
if (!strcmp(availableExtensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
canSwapchain = 1;
@@ -641,10 +662,12 @@ void rvkSelectPhysicalDevice(struct RenderVulkan *vk)
}
for (i = 0; i < nDevices; ++i) {
printf("Checking suitability for\t`%s`...\n", deviceProperties[i].deviceName);
- if (isDeviceSuitable(vk, devices[i], &vk->graphicsIndex)) {
+ uint32_t graphicsIndex;
+ if (isDeviceSuitable(vk, devices[i], &graphicsIndex)) {
printf("Using physical device:\t\t`%s`\n", deviceProperties[i].deviceName);
vk->deviceProperties = deviceProperties[i];
vk->physicalDevice = devices[i];
+ vk->graphicsIndex = graphicsIndex;
printf("Graphics Index:\t\t\t%d\n", vk->graphicsIndex);
goto done;
}