solved all validation issues
authorJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 11 Sep 2024 03:19:41 +0000 (06:19 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 11 Sep 2024 03:19:41 +0000 (06:19 +0300)
src/app.c
src/vk.c
src/vk.h

index 7fff41e..c242b32 100644 (file)
--- a/src/app.c
+++ b/src/app.c
@@ -3,24 +3,29 @@
 #include "app.h"
 #include "vk.h"
 
-struct swapchain {
-       int fb;
-       VkImageView img;
+#define NUM_FRM                2
+
+struct frame {
+       VkCommandBuffer cmdbuf;
        VkSemaphore sem_getimg;
        VkFence imgfence;
 };
 
 int win_width, win_height;
 
+static int frameno;
+
 static int rpass, pipeln, num_swap_img;
-static struct swapchain *swapchain;
+static int *fb;
+static struct frame frame[NUM_FRM];
 static VkSemaphore sem_draw;
 static VkQueue queue;
 
 int app_init(void)
 {
-       int i;
+       int i, qfam;
        unsigned int flags;
+       VkCommandPool cmdpool;
 
        if(vk_init(VKINIT_DEPTH, &flags) == -1) {
                return -1;
@@ -35,21 +40,34 @@ int app_init(void)
        if((num_swap_img = vk_num_swap_images()) <= 0) {
                return -1;
        }
-       if(!(swapchain = malloc(num_swap_img * sizeof *swapchain))) {
+
+       if(!(fb = malloc(num_swap_img * sizeof *fb))) {
+               fprintf(stderr, "failed to allocate default framebuffers\n");
                return -1;
        }
 
        rpass = vk_create_rpass();
 
        for(i=0; i<num_swap_img; i++) {
-               swapchain[i].img = vk_swap_image(i);
-               swapchain[i].fb = vk_create_fb();
-               vk_fb_size(swapchain[i].fb, win_width, win_height);
-               vk_fb_rpass(swapchain[i].fb, rpass);
-               vk_fb_images(swapchain[i].fb, 1, swapchain[i].img);
-
-               swapchain[i].sem_getimg = vk_create_sem();
-               swapchain[i].imgfence = vk_create_fence();
+               fb[i] = vk_create_fb();
+               vk_fb_size(fb[i], win_width, win_height);
+               vk_fb_rpass(fb[i], rpass);
+               vk_fb_images(fb[i], 1, vk_swap_image(i));
+       }
+
+       /* select queue family for the per-frame command buffers */
+       if((qfam = vk_find_qfamily(VKQ_GFX | VKQ_PRESENT)) == -1) {
+               fprintf(stderr, "failed to find a gfx|present-capable queue family\n");
+               return -1;
+       }
+
+       for(i=0; i<NUM_FRM; i++) {
+               if(!(frame[i].cmdbuf = vk_create_cmdbuf_fam(qfam, VK_COMMAND_BUFFER_LEVEL_PRIMARY))) {
+                       fprintf(stderr, "failed to create per-frame command buffer\n");
+                       return -1;
+               }
+               frame[i].sem_getimg = vk_create_sem();
+               frame[i].imgfence = vk_create_fence(1);
        }
 
        pipeln = vk_create_pipeln();
@@ -63,9 +81,17 @@ int app_init(void)
 void app_cleanup(void)
 {
        int i;
+
+       vk_finish();
+
        for(i=0; i<num_swap_img; i++) {
-               vk_free_fence(swapchain[i].imgfence);
-               vk_free_sem(swapchain[i].sem_getimg);
+               vk_free_fb(fb[i]);
+       }
+       vk_free_rpass(rpass);
+
+       for(i=0; i<NUM_FRM; i++) {
+               vk_free_fence(frame[i].imgfence);
+               vk_free_sem(frame[i].sem_getimg);
        }
        vk_free_sem(sem_draw);
        vk_cleanup();
@@ -74,14 +100,15 @@ void app_cleanup(void)
 
 void app_display(void)
 {
-       static int semid = -1;
        int imgid;
        VkCommandBuffer cmdbuf;
+       struct frame *frm;
 
+       frm = frame + (frameno & 1);
        /* get the next image from the swap chain */
-       semid = (semid + 1) % num_swap_img;
-       imgid = vk_next_swap_image(swapchain[semid].sem_getimg);
-       cmdbuf = vk_get_cmdbuf(imgid);
+       vk_wait_fence(frm->imgfence, -1);
+       imgid = vk_next_swap_image(frm->sem_getimg);
+       cmdbuf = frm->cmdbuf;
 
        {
                VkCommandBufferBeginInfo cmdbegin = {0};
@@ -105,7 +132,7 @@ void app_display(void)
 
                rpbegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
                rpbegin.renderPass = vk_rpass(rpass);
-               rpbegin.framebuffer = vk_fb(swapchain[imgid].fb);
+               rpbegin.framebuffer = vk_fb(fb[imgid]);
                vk_rect(&rpbegin.renderArea, 0, 0, win_width, win_height);
                rpbegin.pClearValues = clear;
                rpbegin.clearValueCount = 1;
@@ -119,10 +146,12 @@ void app_display(void)
        }
 
        /* submit the command buffer, wait for one semaphore, signal another */
-       vk_submit(queue, cmdbuf, swapchain[semid].sem_getimg, sem_draw);
+       vk_submit(queue, cmdbuf, frm->sem_getimg, sem_draw, frm->imgfence);
 
        /* swap buffers after drawing is finished */
        vk_present(queue, imgid, sem_draw);
+
+       frameno++;
 }
 
 void app_reshape(int x, int y)
@@ -134,8 +163,8 @@ void app_reshape(int x, int y)
        }
 
        for(i=0; i<vk_num_swap_images(); i++) {
-               vk_fb_size(swapchain[i].fb, x, y);
-               vk_fb_images(swapchain[i].fb, 1, vk_swap_image(i));
+               vk_fb_size(fb[i], x, y);
+               vk_fb_images(fb[i], 1, vk_swap_image(i));
        }
 }
 
index 9c03342..743464f 100644 (file)
--- a/src/vk.c
+++ b/src/vk.c
@@ -84,7 +84,6 @@ static int create_surface(void);
 static int choose_phys_dev(void);
 static int create_device(void);
 static int create_swapchain(void);
-static int create_default_cmdbuf(void);
 
 static void *init_rayext_list(void);
 static int choose_pixfmt(void);
@@ -123,7 +122,6 @@ static int vksc_numimg;
 static VkImage *vksc_img;
 static VkExtent2D vksc_extent;
 static VkImageView *vksc_view;
-static VkCommandBuffer *vksc_cmdbuf;   /* default command buffers (vksc_numimg) */
 
 static VkLayerProperties *inst_layers;
 static VkExtensionProperties *inst_ext, *dev_ext;
@@ -196,20 +194,29 @@ void vk_cleanup(void)
 {
        int i;
 
+       vk_finish();
+
        free(vksc_img);
        vksc_img = 0;
-       free(vksc_view);
-       vksc_view = 0;
        if(vksc_view) {
                for(i=0; i<vksc_numimg; i++) {
                        vkDestroyImageView(vkdev, vksc_view[i], 0);
                }
+               free(vksc_view);
                vksc_view = 0;
        }
        if(vksc) {
                vkDestroySwapchainKHR(vkdev, vksc, 0);
                vksc = 0;
        }
+
+       for(i=0; i<MAX_INIT_QUEUE; i++) {
+               if(initq[i].cmdpool) {
+                       vkDestroyCommandPool(vkdev, initq[i].cmdpool, 0);
+                       initq[i].cmdpool = 0;
+               }
+       }
+
        if(vkdev) {
                vkDestroyDevice(vkdev, 0);
                vkdev = 0;
@@ -252,10 +259,6 @@ int vk_reshape(int xsz, int ysz)
 
        if(create_swapchain() == -1) return -1;
 
-       if(!vksc_cmdbuf) {
-               if(create_default_cmdbuf() == -1) return -1;
-       }
-
        /* TODO create depth/stencil buffers as needed (initflags) */
        return 0;
 }
@@ -280,7 +283,13 @@ int vk_next_swap_image(VkSemaphore sem)
        return -1;
 }
 
-int vk_submit(VkQueue q, VkCommandBuffer cmdbuf, VkSemaphore semwait, VkSemaphore semsig)
+void vk_finish(void)
+{
+       vkDeviceWaitIdle(vkdev);
+}
+
+int vk_submit(VkQueue q, VkCommandBuffer cmdbuf, VkSemaphore semwait,
+               VkSemaphore semsig, VkFence fence)
 {
        /* TODO: investigate if we need to expose the wait stage */
        VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@@ -294,7 +303,7 @@ int vk_submit(VkQueue q, VkCommandBuffer cmdbuf, VkSemaphore semwait, VkSemaphor
        sinf.signalSemaphoreCount = semsig ? 1 : 0;
        sinf.pSignalSemaphores = &semsig;
 
-       if(vkQueueSubmit(q, 1, &sinf, 0) != 0) {
+       if(vkQueueSubmit(q, 1, &sinf, fence) != 0) {
                fprintf(stderr, "failed to submit command buffer\n");
                return -1;
        }
@@ -425,16 +434,6 @@ VkCommandBuffer vk_create_cmdbuf(unsigned int qflags, int level)
        return vk_create_cmdbuf_fam(qfam, level);
 }
 
-VkCommandBuffer vk_get_cmdbuf(int imgid)
-{
-       if(imgid < 0 || imgid >= vksc_numimg) {
-               fprintf(stderr, "vk_get_cmdbuf: invalid id %d, swap chain has %d images\n",
-                               imgid, vksc_numimg);
-               return 0;
-       }
-       return vksc_cmdbuf[imgid];
-}
-
 int vk_create_rpass(void)
 {
        int i;
@@ -1089,12 +1088,15 @@ void vk_free_sem(VkSemaphore sem)
        vkDestroySemaphore(vkdev, sem, 0);
 }
 
-VkFence vk_create_fence(void)
+VkFence vk_create_fence(int state)
 {
        VkFence fence;
        VkFenceCreateInfo finf = {0};
 
        finf.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+       if(state) {
+               finf.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+       }
        if(vkCreateFence(vkdev, &finf, 0, &fence) != 0) {
                return 0;
        }
@@ -1106,6 +1108,12 @@ void vk_free_fence(VkFence fence)
        vkDestroyFence(vkdev, fence, 0);
 }
 
+void vk_wait_fence(VkFence fence, long timeout)
+{
+       vkWaitForFences(vkdev, 1, &fence, VK_TRUE, timeout < 0 ? UINT64_MAX : timeout);
+       vkResetFences(vkdev, 1, &fence);
+}
+
 void vk_rect(VkRect2D *r, int x, int y, int w, int h)
 {
        r->offset.x = x;
@@ -1430,7 +1438,7 @@ static int create_swapchain(void)
 
        scinf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
        scinf.surface = vksurf;
-       scinf.minImageCount = 2;
+       scinf.minImageCount = vksurf_caps.minImageCount;
        scinf.imageFormat = vksurf_fmt[vksurf_selfmt].format;
        scinf.imageColorSpace = vksurf_fmt[vksurf_selfmt].colorSpace;
        scinf.imageExtent = vksc_extent;
@@ -1484,39 +1492,6 @@ static int create_swapchain(void)
        return 0;
 }
 
-static int create_default_cmdbuf(void)
-{
-       int qfam;
-       VkCommandPool cmdpool;
-       VkCommandBufferAllocateInfo cbinf = {0};
-
-       assert(!vksc_cmdbuf);
-
-       if((qfam = vk_find_qfamily(VKQ_GFX | VKQ_PRESENT)) == -1) {
-               fprintf(stderr, "failed to find a gfx|present capable queue family\n");
-               return -1;
-       }
-       if(!(cmdpool = find_cmdpool(qfam))) {
-               fprintf(stderr, "failed to find usable command pool for default command buffers\n");
-               return -1;
-       }
-       if(!(vksc_cmdbuf = malloc(vksc_numimg * sizeof *vksc_cmdbuf))) {
-               fprintf(stderr, "failed to allocate %d command buffers for the swap-chain\n", vksc_numimg);
-               return -1;
-       }
-
-       cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-       cbinf.commandPool = cmdpool;
-       cbinf.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
-       cbinf.commandBufferCount = vksc_numimg;
-
-       if(vkAllocateCommandBuffers(vkdev, &cbinf, vksc_cmdbuf) != 0) {
-               fprintf(stderr, "failed to create %d command buffers for the swap-chain\n", vksc_numimg);
-               return -1;
-       }
-       return 0;
-}
-
 static int eval_pdev_score(VkPhysicalDevice dev)
 {
        int score = 0;
index 4beedf8..e987e96 100644 (file)
--- a/src/vk.h
+++ b/src/vk.h
@@ -71,7 +71,10 @@ VkImageView vk_swap_image(int idx);
 /* returns the image index, or -1 on failure. Pass optional semaphore to signal */
 int vk_next_swap_image(VkSemaphore sem);
 
-int vk_submit(VkQueue q, VkCommandBuffer cmdbuf, VkSemaphore semwait, VkSemaphore semsig);
+void vk_finish(void);
+
+int vk_submit(VkQueue q, VkCommandBuffer cmdbuf, VkSemaphore semwait,
+               VkSemaphore semsig, VkFence fence);
 int vk_present(VkQueue q, int imgid, VkSemaphore semwait);
 
 int vk_find_qfamily(unsigned int flags);
@@ -80,8 +83,6 @@ VkQueue vk_getq(unsigned int flags, int n);
 
 VkCommandBuffer vk_create_cmdbuf_fam(int qfam, int level);
 VkCommandBuffer vk_create_cmdbuf(unsigned int qflags, int level);
-/* return one of the swap-chain command buffers */
-VkCommandBuffer vk_get_cmdbuf(int imgid);
 
 int vk_create_rpass(void);
 void vk_free_rpass(int rp);
@@ -128,8 +129,9 @@ void vk_free_shader(VkShaderModule sdr);
 VkSemaphore vk_create_sem(void);
 void vk_free_sem(VkSemaphore sem);
 
-VkFence vk_create_fence(void);
+VkFence vk_create_fence(int state);
 void vk_free_fence(VkFence fence);
+void vk_wait_fence(VkFence fence, long timeout);       /* -1 = inf */
 
 /* random helpers */
 void vk_rect(VkRect2D *r, int x, int y, int w, int h);