summaryrefslogtreecommitdiff
path: root/render/vulkan/renderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/vulkan/renderer.c')
-rw-r--r--render/vulkan/renderer.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c
new file mode 100644
index 0000000..91dc3fb
--- /dev/null
+++ b/render/vulkan/renderer.c
@@ -0,0 +1,167 @@
+#include <vulkan/vulkan.h>
+#include <GLFW/glfw3.h>
+#include <rune/ui/renderer.h>
+#include <rune/core/logging.h>
+#include <rune/core/alloc.h>
+#include <rune/core/abort.h>
+#include "context.h"
+#include "image.h"
+#include <sys/time.h>
+
+static struct vkcontext *context = NULL;
+
+void _init_cmdbuffers(void) {
+ uint32_t num_buffers = context->swapchain->img_count;
+ if (context->cmdbuffers == NULL)
+ context->cmdbuffers = rune_calloc(0, sizeof(struct vkcmdbuffer*) * num_buffers);
+
+ for (uint32_t i = 0; i < num_buffers; i++) {
+ if (context->cmdbuffers[i] != NULL)
+ destroy_vkcmdbuffer(context->cmdbuffers[i], context->dev);
+ context->cmdbuffers[i] = create_vkcmdbuffer(context->dev, 1);
+ }
+ log_output(LOG_DEBUG, "Created %d command buffers", num_buffers);
+}
+
+void _destroy_cmdbuffers(void) {
+ uint32_t num_buffers = context->swapchain->img_count;
+ if (context->cmdbuffers == NULL)
+ return;
+ for (uint32_t i = 0; i < num_buffers; i++) {
+ if (context->cmdbuffers[i] != NULL)
+ destroy_vkcmdbuffer(context->cmdbuffers[i], context->dev);
+ }
+ log_output(LOG_DEBUG, "Destroyed %d command buffers", num_buffers);
+}
+
+void _init_framebuffers(void) {
+ uint32_t num_buffers = context->swapchain->img_count;
+ if (context->framebuffers == NULL)
+ context->framebuffers = rune_calloc(0, sizeof(struct vkframebuffer*) * num_buffers);
+
+ uint32_t at_count = 2;
+ for (uint32_t i = 0; i < num_buffers; i++) {
+ VkImageView attachments[at_count];
+ attachments[0] = context->swapchain->views[i];
+ attachments[1] = context->swapchain->depth_attachment->view;
+
+ if (context->framebuffers[i] != NULL)
+ destroy_vkframebuffer(context->framebuffers[i], context->dev);
+ context->framebuffers[i] = create_vkframebuffer(context->dev,
+ context->rendpass,
+ context->surface->width,
+ context->surface->height,
+ at_count,
+ attachments);
+ }
+ log_output(LOG_DEBUG, "Created %d frame buffers", num_buffers);
+}
+
+void _destroy_framebuffers(void) {
+ uint32_t num_buffers = context->swapchain->img_count;
+ if (context->framebuffers == NULL)
+ return;
+
+ for (uint32_t i = 0; i < num_buffers; i++)
+ destroy_vkframebuffer(context->framebuffers[i], context->dev);
+ log_output(LOG_DEBUG, "Destroyed %d frame buffers", num_buffers);
+}
+
+int _init_vulkan(struct rune_window *window) {
+ struct timeval start;
+ struct timeval stop;
+ gettimeofday(&start, NULL);
+
+ struct ext_container ext;
+ ext.extensions = glfwGetRequiredInstanceExtensions(&ext.ext_count);
+ struct vklayer_container *vklayers = init_vklayers(&ext);
+
+ context = create_vkcontext(vklayers, &ext);
+ if (context == NULL)
+ return -1;
+
+ VkResult res = glfwCreateWindowSurface(context->instance,
+ window->window,
+ NULL,
+ &context->surface->handle);
+ if (res != VK_SUCCESS) {
+ log_output(LOG_FATAL, "Cannot create rendering surface");
+ return -1;
+ }
+
+ context->dev = create_vkdev(context->instance,
+ context->surface->handle);
+ if (context->dev == NULL)
+ return -1;
+
+ context->surface->width = window->winw;
+ context->surface->height = window->winh;
+ context->swapchain = create_swapchain(context->surface, context->dev);
+ if (context->swapchain == NULL)
+ return -1;
+
+ vec4 area = {0, 0, context->surface->width, context->surface->height};
+ vec4 color = {0, 0, 0, 1.0f};
+ context->rendpass = create_vkrendpass(context->dev, context->swapchain, area, color, 1.0, 0);
+ if (context->rendpass == NULL)
+ return -1;
+
+ _init_framebuffers();
+ _init_cmdbuffers();
+
+ context->image_semaphores = rune_alloc(sizeof(VkSemaphore) * context->swapchain->max_frames);
+ context->queue_semaphores = rune_alloc(sizeof(VkSemaphore) * context->swapchain->max_frames);
+ context->fences_in_flight = rune_calloc(0, sizeof(struct vkfence*) * context->swapchain->max_frames);
+
+ VkSemaphoreCreateInfo scinfo;
+ for (uint8_t i = 0; i < context->swapchain->max_frames; i++) {
+ scinfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ scinfo.pNext = NULL;
+ scinfo.flags = 0;
+ vkCreateSemaphore(context->dev->ldev, &scinfo, NULL, &context->image_semaphores[i]);
+ vkCreateSemaphore(context->dev->ldev, &scinfo, NULL, &context->queue_semaphores[i]);
+ context->fences_in_flight[i] = create_vkfence(context->dev, 1);
+ }
+ context->images_in_flight = rune_calloc(0, sizeof(struct vkfence*) * context->swapchain->img_count);
+
+ gettimeofday(&stop, NULL);
+ log_output(LOG_INFO, "Finished initializing Vulkan in %lums", (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec);
+ return 0;
+}
+
+void _close_vulkan(void) {
+ vkDeviceWaitIdle(context->dev->ldev);
+ for (uint8_t i = 0; i < context->swapchain->max_frames; i++) {
+ if (context->image_semaphores[i] != NULL)
+ vkDestroySemaphore(context->dev->ldev, context->image_semaphores[i], NULL);
+ if (context->queue_semaphores[i] != NULL)
+ vkDestroySemaphore(context->dev->ldev, context->queue_semaphores[i], NULL);
+ destroy_vkfence(context->fences_in_flight[i], context->dev);
+ }
+
+ _destroy_cmdbuffers();
+ _destroy_framebuffers();
+ destroy_vkrendpass(context->rendpass, context->dev);
+ destroy_swapchain(context->swapchain, context->dev);
+ destroy_vkdev(context->dev);
+ destroy_vkcontext(context);
+}
+
+void _draw_vulkan(void) {
+ if (fence_lock(context->fences_in_flight[context->swapchain->frame], context->dev, UINT64_MAX) != 0)
+ log_output(LOG_WARN, "In-flight fence locking failure");
+}
+
+void _clear_vulkan(void) {
+}
+
+struct rune_renderer* select_render_vulkan(struct rune_window *window) {
+ struct rune_renderer *ret = rune_alloc(sizeof(struct rune_renderer));
+ ret->init = _init_vulkan;
+ ret->close = _close_vulkan;
+ ret->draw = _draw_vulkan;
+ ret->clear = _clear_vulkan;
+ if ((*ret->init)(window) != 0)
+ rune_abort();
+ return ret;
+}