framebuffers
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 14 Aug 2022 04:34:51 +0000 (07:34 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 14 Aug 2022 04:34:51 +0000 (07:34 +0300)
src/vk.c
src/vk.h

index 0749f07..ca03b35 100644 (file)
--- a/src/vk.c
+++ b/src/vk.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
+#include <stdarg.h>
 #include <vulkan/vulkan.h>
 #include "vk.h"
 #include "util.h"
 #include <vulkan/vulkan_xcb.h>
 #endif
 
+struct rpass {
+       int used;
+       int fmt;
+       int zfmt;
+       int num_colbuf;
+       int num_samples;
+       int clear;
+
+       int vkobj_valid;
+       VkRenderPass vkobj;
+};
+
+#define MAX_FB_IMGV    8
+struct framebuf {
+       int used;
+       int width, height;
+
+       /* if rpasses[rpidx].vkobj != vkrpass, the framebuf is invalid */
+       int rpidx;
+       VkRenderPass vkrpass;
+
+       VkImageView imgv[MAX_FB_IMGV];
+       int num_imgv;
+
+       int vkobj_valid;
+       VkFramebuffer vkobj;
+};
+
+
+static struct rpass *rpasses;
+static struct framebuf *framebufs;
+
+
 static int create_instance(void);
 static int create_surface(void);
 static int choose_phys_dev(void);
@@ -142,20 +176,6 @@ int vk_reshape(int xsz, int ysz)
        return 0;
 }
 
-struct rpass {
-       int used;
-       int fmt;
-       int zfmt;
-       int num_colbuf;
-       int num_samples;
-       /* TODO: stuff about depth-stencil */
-       int clear;
-
-       int vkobj_valid;
-       VkRenderPass vkobj;
-};
-
-static struct rpass *rpasses;
 
 int vk_create_rpass(void)
 {
@@ -212,11 +232,13 @@ void vk_rpass_colorbuf(int rp, int fmt, int n)
 void vk_rpass_msaa(int rp, int nsamp)
 {
        rpasses[rp].num_samples = nsamp;
+       rpasses[rp].vkobj_valid = 0;
 }
 
 void vk_rpass_clear(int rp, int clear)
 {
        rpasses[rp].clear = clear;
+       rpasses[rp].vkobj_valid = 0;
 }
 
 VkRenderPass vk_rpass(int rp)
@@ -231,6 +253,11 @@ VkRenderPass vk_rpass(int rp)
        r = rpasses + rp;
 
        if(!r->vkobj_valid) {
+               if(r->vkobj) {
+                       vkDestroyRenderPass(vkdev, r->vkobj, 0);
+                       r->vkobj = 0;
+               }
+
                zidx = r->num_colbuf;
                memset(att, 0, sizeof att);
                for(i=0; i<r->num_colbuf; i++) {
@@ -282,6 +309,125 @@ VkRenderPass vk_rpass(int rp)
        return r->vkobj;
 }
 
+
+int vk_create_fb(void)
+{
+       int i;
+       struct framebuf framebuf = {0}, *fb = &framebuf;
+
+       if(!framebufs) {
+               framebufs = darr_alloc(0, sizeof *framebufs);
+               darr_push(framebufs, &framebuf);        /* add dummy rpass */
+       }
+
+       for(i=1; i<darr_size(framebufs); i++) {
+               if(!framebufs[i].used) {
+                       fb = framebufs + i;
+               }
+       }
+
+       /* init framebuffer defaults */
+       memset(fb, 0, sizeof &fb);
+       fb->used = 1;
+
+       if(fb == &framebuf) {
+               darr_push(framebufs, fb);
+               return darr_size(framebufs) - 1;
+       }
+       return fb - framebufs;
+}
+
+void vk_free_fb(int fb)
+{
+       if(!framebufs || fb < 1 || fb >= darr_size(framebufs)) {
+               return;
+       }
+
+       if(framebufs[fb].used && framebufs[fb].vkobj) {
+               vkDestroyFramebuffer(vkdev, framebufs[fb].vkobj, 0);
+       }
+       framebufs[fb].used = 0;
+}
+
+void vk_fb_size(int fb, int x, int  y)
+{
+       framebufs[fb].width = x;
+       framebufs[fb].height = y;
+       framebufs[fb].vkobj_valid = 0;
+}
+
+void vk_fb_rpass(int fb, int rpass)
+{
+       if(rpass < 0 || rpass >= darr_size(rpasses) || !rpasses[rpass].used) {
+               fprintf(stderr, "vk_fb_rpass: %d is not a valid renderpass\n", rpass);
+               return;
+       }
+
+       framebufs[fb].rpidx = rpass;
+       if(rpasses[rpass].vkobj_valid) {
+               framebufs[fb].vkrpass = rpasses[rpass].vkobj;
+       } else {
+               framebufs[fb].vkrpass = 0;
+       }
+       framebufs[fb].vkobj_valid = 0;
+}
+
+void vk_fb_images(int fb, int n, ...)
+{
+       int i;
+       va_list ap;
+
+       if(n > MAX_FB_IMGV) {
+               fprintf(stderr, "vk_fb_images: %d is too many images\n", n);
+               n = MAX_FB_IMGV;
+       }
+
+       va_start(ap, n);
+       for(i=0; i<n; i++) {
+               framebufs[fb].imgv[i] = va_arg(ap, VkImageView);
+       }
+       va_end(ap);
+       framebufs[fb].num_imgv = n;
+       framebufs[fb].vkobj_valid = 0;
+}
+
+VkFramebuffer vk_fb(int fb)
+{
+       VkFramebufferCreateInfo fbinf;
+       VkRenderPass rpass;
+       struct framebuf *f;
+
+       f = framebufs + fb;
+
+       if(!(rpass = vk_rpass(f->rpidx))) {
+               return 0;
+       }
+
+       if(rpass != f->vkrpass || !f->vkobj_valid) {
+               f->vkrpass = rpass;
+               if(f->vkobj) {
+                       vkDestroyFramebuffer(vkdev, f->vkobj, 0);
+                       f->vkobj = 0;
+               }
+
+               memset(&fbinf, 0, sizeof fbinf);
+               fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+               fbinf.renderPass = rpass;
+               fbinf.attachmentCount = f->num_imgv;
+               fbinf.pAttachments = f->imgv;
+               fbinf.width = f->width;
+               fbinf.height = f->height;
+
+               if(vkCreateFramebuffer(vkdev, &fbinf, 0, &f->vkobj) != 0) {
+                       fprintf(stderr, "vk_fb: failed to create framebuffer\n");
+                       return 0;
+               }
+               f->vkobj_valid = 1;
+       }
+       return f->vkobj;
+}
+
+
 #define ARRSZ(arr)     (sizeof arr / sizeof *arr)
 static const char *known_layer_list[] = {
        "VK_LAYER_GOOGLE_threading",
index 3322f14..470f757 100644 (file)
--- a/src/vk.h
+++ b/src/vk.h
@@ -24,5 +24,13 @@ void vk_rpass_msaa(int rp, int nsamp);
 void vk_rpass_clear(int rp, int clear);
 VkRenderPass vk_rpass(int rp);
 
+int vk_create_fb(void);
+void vk_free_fb(int fb);
+void vk_fb_size(int fb, int x, int y);
+void vk_fb_rpass(int fb, int rpass);
+void vk_fb_images(int fb, int n, ...);
+VkFramebuffer vk_fb(int fb);
+
+
 
 #endif /* VK_H_ */