summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorJordan Halase <jordan@halase.me>2019-11-02 02:52:13 -0500
committerJordan Halase <jordan@halase.me>2019-11-02 02:52:13 -0500
commit39d7d87be2eb32c9a25f2b85ba9288e0e590a2ad (patch)
tree47fa9f885d8d9837672796914227dbc663da8d05 /main.c
parent1956c720cd96e3d3d95d2d1930038f74fd03aafb (diff)
Get absolute minimum working
Diffstat (limited to 'main.c')
-rw-r--r--main.c177
1 files changed, 125 insertions, 52 deletions
diff --git a/main.c b/main.c
index 77b2d3b..68b43aa 100644
--- a/main.c
+++ b/main.c
@@ -124,16 +124,23 @@ struct SwapchainVulkan {
VkImageView *imageViews;
};
-/** Vulkan application that uses Pugl for windows and events */
+/** Vulkan application that uses Pugl for windows and events
+ *
+ * TODO: Separate Instance from rest of application.
+ * All Pugl stuff must be destroyed AFTER freeing the surface but BEFORE
+ * freeing the instance. Right now we are forced to destroy them inside of
+ * `rvkDestroy` even though the user creates them.
+ */
struct RenderVulkan {
struct VulkanAPI *api;
struct VulkanDev *dev;
PuglWorld *world;
+ PuglView *view;
char *errMsg;
VkInstance instance;
VkDebugReportCallbackEXT debugCallback;
VkSurfaceKHR surface;
- VkPhysicalDeviceProperties deviceProperties;
+ VkPhysicalDeviceProperties deviceProperties; // TODO: Put this on the heap
VkPhysicalDevice physicalDevice;
uint32_t graphicsIndex;
VkDevice device;
@@ -1025,23 +1032,6 @@ int rvkOpenDevice(struct RenderVulkan *vk)
return 0;
}
-static void rvkCloseDevice(struct RenderVulkan *vk)
-{
- if (vk->commandPool) {
- vk->dev->vkDestroyCommandPool(vk->device, vk->commandPool, ALLOC_VK);
- vk->commandPool = VK_NULL_HANDLE;
- }
- vk->graphicsQueue = VK_NULL_HANDLE;
- if (vk->dev->vkDestroyDevice) {
- vk->dev->vkDestroyDevice(vk->device, ALLOC_VK);
- } else {
- fprintf(stderr, "Fatal: Unable to destroy logical device (missing function pointer)\n");
- }
- free(vk->dev);
- vk->dev = NULL;
- vk->device = VK_NULL_HANDLE;
-}
-
static int rvkCreateRawSwapchain(struct RenderVulkan *vk, int width, int height)
{
VkSurfaceCapabilitiesKHR surfaceCapabilities;
@@ -1119,20 +1109,28 @@ static int rvkCreateRawSwapchain(struct RenderVulkan *vk, int width, int height)
static void rvkDestroyRawSwapchain(struct RenderVulkan *vk)
{
- vk->dev->vkDestroySwapchainKHR(vk->device, vk->swapchain.rawSwapchain, ALLOC_VK);
- memset(&vk->swapchain.surfaceFormat, 0, sizeof(vk->swapchain.surfaceFormat));
- memset(&vk->swapchain, 0, sizeof(vk->swapchain));
+ if (vk->swapchain.rawSwapchain) {
+ vk->dev->vkDestroySwapchainKHR(vk->device, vk->swapchain.rawSwapchain, ALLOC_VK);
+ memset(&vk->swapchain.surfaceFormat, 0, sizeof(vk->swapchain.surfaceFormat));
+ memset(&vk->swapchain, 0, sizeof(vk->swapchain));
+ }
}
static VkResult createSwapchainImageViews(VkDevice device,
const struct VulkanDev *const dev, struct SwapchainVulkan *const swapchain)
{
- dev->vkGetSwapchainImagesKHR(device, swapchain->rawSwapchain, &swapchain->nImages, NULL);
+ VkResult result;
+ if ((result = dev->vkGetSwapchainImagesKHR(device, swapchain->rawSwapchain, &swapchain->nImages, NULL))) {
+ return result;
+ }
swapchain->images = calloc(swapchain->nImages, sizeof(*swapchain->images));
- dev->vkGetSwapchainImagesKHR(device, swapchain->rawSwapchain, &swapchain->nImages, swapchain->images);
- //swapchain->imageViews = calloc(swapchain->nImages, sizeof(*swapchain->imageViews));
+ if ((result = dev->vkGetSwapchainImagesKHR(device, swapchain->rawSwapchain, &swapchain->nImages, swapchain->images))) {
+ return result;
+ }
+#if 0
+ /* We don't need this yet until we start using as a render target. */
+ swapchain->imageViews = calloc(swapchain->nImages, sizeof(*swapchain->imageViews));
- VkResult result;
for (uint32_t i = 0; i < swapchain->nImages; ++i) {
VkImageViewCreateInfo createInfo = { 0 };
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -1148,23 +1146,34 @@ static VkResult createSwapchainImageViews(VkDevice device,
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
- // if ((result = dev->vkCreateImageView(device, &createInfo, ALLOC_VK, &swapchain->imageViews[i]))) {
- // return result;
- // }
+ if ((result = dev->vkCreateImageView(device, &createInfo, ALLOC_VK, &swapchain->imageViews[i]))) {
+ return result;
+ }
}
+#endif
return VK_SUCCESS;
}
static void destroySwapchainImageViews(VkDevice device,
- const struct VulkanDev *const dev, struct SwapchainVulkan *const swapchain)
+ const struct VulkanDev *const dev,
+ struct SwapchainVulkan *const swapchain)
{
- for (uint32_t i = 0; i < swapchain->nImages; ++i) {
- dev->vkDestroyImageView(device, swapchain->imageViews[i], ALLOC_VK);
+ if (swapchain->imageViews) {
+ for (uint32_t i = 0; i < swapchain->nImages; ++i) {
+ if (swapchain->imageViews[i]) {
+ dev->vkDestroyImageView(device,
+ swapchain->imageViews[i],
+ ALLOC_VK);
+ }
+ }
+ free(swapchain->imageViews);
+ swapchain->imageViews = NULL;
+ }
+ if (swapchain->images) {
+ free(swapchain->images);
+ swapchain->images = NULL;
+ swapchain->nImages = 0;
}
- free(swapchain->imageViews);
- free(swapchain->images);
- swapchain->imageViews = NULL;
- swapchain->images = NULL;
}
static VkResult allocateCommandBuffers(struct RenderVulkan *vk)
@@ -1180,9 +1189,14 @@ static VkResult allocateCommandBuffers(struct RenderVulkan *vk)
static void freeCommandBuffers(struct RenderVulkan *vk)
{
- vk->dev->vkFreeCommandBuffers(vk->device, vk->commandPool, vk->swapchain.nImages, vk->commandBuffers);
- free(vk->commandBuffers);
- vk->commandBuffers = NULL;
+ if (vk->commandBuffers) {
+ vk->dev->vkFreeCommandBuffers(vk->device,
+ vk->commandPool,
+ vk->swapchain.nImages,
+ vk->commandBuffers);
+ free(vk->commandBuffers);
+ vk->commandBuffers = NULL;
+ }
}
static int recordCommandBuffers(struct RenderVulkan *vk)
@@ -1270,6 +1284,13 @@ int rvkCreateSwapchain(struct RenderVulkan *vk, const int width, const int heigh
return 0;
}
+void rvkDestroySwapchain(struct RenderVulkan *vk)
+{
+ freeCommandBuffers(vk);
+ destroySwapchainImageViews(vk->device, vk->dev, &vk->swapchain);
+ rvkDestroyRawSwapchain(vk);
+}
+
/** Creates any semaphores or fences for this application. */
int rvkCreateSyncObjects(struct RenderVulkan *vk)
{
@@ -1280,27 +1301,82 @@ int rvkCreateSyncObjects(struct RenderVulkan *vk)
return 0;
}
+void rvkDestroySyncObjects(struct RenderVulkan *vk)
+{
+ if (vk->sync.semaphore.renderFinished) {
+ vk->dev->vkDestroySemaphore(vk->device, vk->sync.semaphore.renderFinished, ALLOC_VK);
+ vk->sync.semaphore.renderFinished = VK_NULL_HANDLE;
+ }
+ if (vk->sync.semaphore.imageAvailable) {
+ vk->dev->vkDestroySemaphore(vk->device, vk->sync.semaphore.imageAvailable, ALLOC_VK);
+ vk->sync.semaphore.imageAvailable = VK_NULL_HANDLE;
+ }
+}
+
+static void rvkCloseDevice(struct RenderVulkan *vk)
+{
+ if (vk->device) {
+ if (vk->dev->vkDeviceWaitIdle) vk->dev->vkDeviceWaitIdle(vk->device);
+ rvkDestroySyncObjects(vk);
+ rvkDestroySwapchain(vk);
+ if (vk->commandPool) {
+ vk->dev->vkDestroyCommandPool(vk->device, vk->commandPool, ALLOC_VK);
+ vk->commandPool = VK_NULL_HANDLE;
+ }
+ vk->graphicsQueue = VK_NULL_HANDLE;
+ /* `vk->device` implies `vk->dev` but device functions MAY not
+ * be loaded.
+ * However, all subobjects of `vk->device` imply functions loaded
+ */
+ if (vk->dev->vkDestroyDevice) {
+ vk->dev->vkDestroyDevice(vk->device, ALLOC_VK);
+ } else {
+ /* This is only theoretical, because we must load the "destroy"
+ * function *after* we create the device
+ */
+ fprintf(stderr, "Fatal: Unable to destroy logical device (missing function pointer)\n");
+ }
+ free(vk->dev);
+ vk->dev = NULL;
+ vk->device = VK_NULL_HANDLE;
+ }
+}
+
/** This must work no matter the current state of `vk` */
void rvkDestroy(struct RenderVulkan *vk)
{
if (vk) {
- /* `vk->device` implies `vk->dev` but device functions MAY not be loaded */
- if (vk->device) {
- if (vk->dev->vkDeviceWaitIdle) vk->dev->vkDeviceWaitIdle(vk->device);
- rvkDestroyRawSwapchain(vk);
- rvkCloseDevice(vk);
+ rvkCloseDevice(vk);
+ if (vk->surface) {
+ vk->api->vkDestroySurfaceKHR(vk->instance, vk->surface, ALLOC_VK);
+ vk->surface = VK_NULL_HANDLE;
+ }
+ /* PuglView must be freed AFTER surface but BEFORE instance destroy */
+ if (vk->view) {
+ puglFreeView(vk->view);
+ vk->view = NULL;
}
- if (vk->surface) vk->api->vkDestroySurfaceKHR(vk->instance, vk->surface, ALLOC_VK);
if (vk->debugCallback) {
/* `vk->debugCallback` implies `vk->api` and all instance functions loaded */
vk->api->vkDestroyDebugReportCallbackEXT(vk->instance, vk->debugCallback, ALLOC_VK);
+ vk->debugCallback = VK_NULL_HANDLE;
+ }
+ /* PuglWorld must be unloaded AFTER PuglView but BEFORE instance destroy */
+ puglFreeWorld(vk->world);
+ vk->world = NULL;
+ if (vk->instance) {
+ rvkDestroyInstance(vk);
+ vk->instance = VK_NULL_HANDLE;
}
- if (vk->instance) rvkDestroyInstance(vk);
if (vk->api) {
if (vk->api->handle) unloadVulkanLibrary(vk->api->handle);
free(vk->api);
+ vk->api = NULL;
+ }
+ if (vk->errMsg) {
+ free(vk->errMsg);
+ vk->errMsg = NULL;
}
- if (vk->errMsg) free(vk->errMsg);
free(vk);
}
}
@@ -1402,7 +1478,6 @@ int main()
CHECK_RVK(vk, rvkCreate(world, &vk));
printf("Created Vulkan Instance Successfully\n");
-
PuglView *view = puglNewView(world);
const PuglRect frame = { 0, 0, 800, 600 };
puglSetFrame(view, frame);
@@ -1414,7 +1489,7 @@ int main()
fprintf(stderr, "Could not create window: %d\n", status);
rvkFatal(vk);
}
- puglSetEventFunc(view, onEvent);
+ vk->view = view;
CHECK_RVK(vk, rvkCreateSurface(vk, view));
CHECK_RVK(vk, rvkSelectPhysicalDevice(vk));
@@ -1424,15 +1499,13 @@ int main()
printf("Opened Vulkan Device Successfully\n");
+ puglSetEventFunc(view, onEvent);
puglShowWindow(view);
while (running) {
puglPollEvents(world, -1);
puglDispatchEvents(world);
}
- puglFreeView(view);
- puglFreeWorld(world);
- /* Vulkan library MUST be unloaded AFTER call to XCloseDisplay() or it will segfault (?) */
rvkDestroy(vk);
printf("Exiting gracefully\n");
return 0;