summaryrefslogtreecommitdiff
path: root/render/vulkan/renderpass.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/vulkan/renderpass.c')
-rw-r--r--render/vulkan/renderpass.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/render/vulkan/renderpass.c b/render/vulkan/renderpass.c
new file mode 100644
index 0000000..59d1c26
--- /dev/null
+++ b/render/vulkan/renderpass.c
@@ -0,0 +1,172 @@
+#include "renderpass.h"
+#include "vkassert.h"
+#include <rune/core/alloc.h>
+
+struct vkcmdbuffer* create_vkcmdbuffer(struct vkdev *dev, int primary) {
+ struct vkcmdbuffer *ret = rune_calloc(0, sizeof(struct vkcmdbuffer));
+
+ VkCommandBufferAllocateInfo ainfo;
+ ainfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ ainfo.pNext = NULL;
+ ainfo.commandPool = dev->cmd_pool;
+ if (primary == 1)
+ ainfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ else
+ ainfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
+ ainfo.commandBufferCount = 1;
+ vkassert(vkAllocateCommandBuffers(dev->ldev, &ainfo, &ret->handle), "Failed to initialize command buffer");
+
+ ret->state = CMDBUF_READY;
+ return ret;
+}
+
+void destroy_vkcmdbuffer(struct vkcmdbuffer *cmdbuffer, struct vkdev *dev) {
+ vkFreeCommandBuffers(dev->ldev, dev->cmd_pool, 1, &cmdbuffer->handle);
+ rune_free(cmdbuffer);
+}
+
+void cmdbuf_begin(struct vkcmdbuffer *cmdbuffer, int single, int rpass_cont, int sim_use) {
+ VkCommandBufferBeginInfo binfo;
+ binfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ binfo.flags = 0;
+ binfo.pNext = NULL;
+ if (single)
+ binfo.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ if (rpass_cont)
+ binfo.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
+ if (sim_use)
+ binfo.flags |= VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
+ vkassert(vkBeginCommandBuffer(cmdbuffer->handle, &binfo), "Cannot record commands into command buffer");
+ cmdbuffer->state = CMDBUF_RECORD;
+}
+
+void cmdbuf_end(struct vkcmdbuffer *cmdbuffer) {
+ vkassert(vkEndCommandBuffer(cmdbuffer->handle), "Cannot end command buffer recording");
+ cmdbuffer->state = CMDBUF_ENDREC;
+}
+
+struct vkcmdbuffer* cmdbuf_begin_single_use(struct vkdev *dev) {
+ struct vkcmdbuffer *ret = create_vkcmdbuffer(dev, 1);
+ cmdbuf_begin(ret, 1, 0, 0);
+ return ret;
+}
+
+void cmdbuf_end_single_use(struct vkcmdbuffer *cmdbuffer, struct vkdev *dev, VkQueue queue) {
+ cmdbuf_end(cmdbuffer);
+ VkSubmitInfo sinfo;
+ sinfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ sinfo.pNext = NULL;
+ sinfo.waitSemaphoreCount = 0;
+ sinfo.pWaitSemaphores = NULL;
+ sinfo.pWaitDstStageMask = NULL;
+ sinfo.commandBufferCount = 1;
+ sinfo.pCommandBuffers = &cmdbuffer->handle;
+ sinfo.signalSemaphoreCount = 0;
+ sinfo.pSignalSemaphores = NULL;
+ vkassert(vkQueueSubmit(queue, 1, &sinfo, 0), "Cannot submit single use command buffer");
+
+ vkassert(vkQueueWaitIdle(queue), "Error while waiting for Vulkan queue");
+ destroy_vkcmdbuffer(cmdbuffer, dev);
+}
+
+struct vkrendpass* create_vkrendpass(struct vkdev *dev, struct vkswapchain *swapchain, vec4 area, vec4 color, float depth, uint32_t stencil) {
+ VkAttachmentDescription atdesc[2];
+ atdesc[0].flags = 0;
+ atdesc[0].format = swapchain->format;
+ atdesc[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ atdesc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ atdesc[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ atdesc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ atdesc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ atdesc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ atdesc[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ atdesc[1].flags = 0;
+ atdesc[1].format = dev->depth_format;
+ atdesc[1].samples = VK_SAMPLE_COUNT_1_BIT;
+ atdesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ atdesc[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ atdesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ atdesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ atdesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ atdesc[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference cref;
+ cref.attachment = 0;
+ cref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference dref;
+ dref.attachment = 1;
+ dref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass;
+ subpass.flags = 0;
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &cref;
+ subpass.pDepthStencilAttachment = &dref;
+ subpass.preserveAttachmentCount = 0;
+ subpass.pPreserveAttachments = NULL;
+ subpass.inputAttachmentCount = 0;
+ subpass.pInputAttachments = NULL;
+
+ VkSubpassDependency dep;
+ dep.srcSubpass = VK_SUBPASS_EXTERNAL;
+ dep.dstSubpass = 0;
+ dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dep.srcAccessMask = 0;
+ dep.dstAccessMask = 0;
+ dep.dependencyFlags = 0;
+
+ struct vkrendpass *ret = rune_alloc(sizeof(struct vkrendpass));
+ VkRenderPassCreateInfo rcinfo;
+ rcinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rcinfo.pNext = NULL;
+ rcinfo.flags = 0;
+ rcinfo.attachmentCount = 2;
+ rcinfo.pAttachments = atdesc;
+ rcinfo.subpassCount = 1;
+ rcinfo.pSubpasses = &subpass;
+ rcinfo.dependencyCount = 1;
+ rcinfo.pDependencies = &dep;
+ vkassert(vkCreateRenderPass(dev->ldev, &rcinfo, NULL, &ret->handle), "Failed to create renderpass");
+
+ log_output(LOG_DEBUG, "Initialized renderpass");
+ return ret;
+}
+
+void destroy_vkrendpass(struct vkrendpass *rendpass, struct vkdev *dev) {
+ if (rendpass->handle)
+ vkDestroyRenderPass(dev->ldev, rendpass->handle, NULL);
+ rune_free(rendpass);
+}
+
+void renderpass_begin(struct vkcmdbuffer *buf, struct vkrendpass *rendpass, VkFramebuffer framebuf) {
+ VkClearValue cvals[2];
+ cvals[0].color.float32[0] = rendpass->color[0];
+ cvals[0].color.float32[1] = rendpass->color[1];
+ cvals[0].color.float32[2] = rendpass->color[2];
+ cvals[0].color.float32[3] = rendpass->color[3];
+ cvals[1].depthStencil.depth = rendpass->depth;
+ cvals[1].depthStencil.stencil = rendpass->stencil;
+
+ VkRenderPassBeginInfo binfo;
+ binfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ binfo.renderPass = rendpass->handle;
+ binfo.framebuffer = framebuf;
+ binfo.renderArea.offset.x = rendpass->area[0];
+ binfo.renderArea.offset.y = rendpass->area[1];
+ binfo.renderArea.extent.width = rendpass->area[2];
+ binfo.renderArea.extent.height = rendpass->area[3];
+ binfo.clearValueCount = 2;
+ binfo.pClearValues = cvals;
+
+ vkCmdBeginRenderPass(buf->handle, &binfo, VK_SUBPASS_CONTENTS_INLINE);
+ buf->state = CMDBUF_RPASS;
+}
+
+void renderpass_end(struct vkcmdbuffer *buf, struct vkrendpass *rendpass) {
+ vkCmdEndRenderPass(buf->handle);
+ buf->state = CMDBUF_RECORD;
+}