queue family selection
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 16 Aug 2022 04:06:05 +0000 (07:06 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 16 Aug 2022 04:06:05 +0000 (07:06 +0300)
src/vk.c
src/vk.h

index ca03b35..82b1ccf 100644 (file)
--- a/src/vk.c
+++ b/src/vk.c
@@ -65,9 +65,9 @@ static int initflags;
 
 static VkInstance vk;
 static VkPhysicalDevice vkpdev;
-static int vkqfam_idx, vkqfam_maxq;
+static VkQueueFamilyProperties *qfam;
+static uint32_t num_qfam;
 static VkDevice vkdev;
-static VkQueue vkq;
 static VkSurfaceKHR vksurf;
 static VkSurfaceCapabilitiesKHR vksurf_caps;
 static int vksurf_numfmt, vksurf_selfmt;
@@ -176,6 +176,51 @@ int vk_reshape(int xsz, int ysz)
        return 0;
 }
 
+int vk_find_qfamily(unsigned int flags)
+{
+       int i, famidx = -1;
+       VkBool32 can_pres;
+
+       if(!qfam) return -1;    /* not initialized I guess... */
+
+       for(i=0; i<num_qfam; i++) {
+               vkGetPhysicalDeviceSurfaceSupportKHR(vkpdev, i, vksurf, &can_pres);
+
+               if((flags & VKQ_PRESENT) && !can_pres) {
+                       continue;
+               }
+               if((flags & VKQ_GFX) && !(qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
+                       continue;
+               }
+               if((flags & VKQ_COMPUTE) && !(qfam[i].queueFlags & VK_QUEUE_COMPUTE_BIT)) {
+                       continue;
+               }
+
+               return i;       /* found a suitabe queue family */
+       }
+
+       return -1;
+}
+
+VkQueue vk_getq_fam(int fam, int n)
+{
+       VkQueue q;
+
+       if(fam < 0) return 0;
+       if(n < 0 || n >= qfam[fam].queueCount) {
+               fprintf(stderr, "vk_getq_fam: invalid index %d, family %d has %d queues\n",
+                          n, fam, qfam[fam].queueCount);
+               return 0;
+       }
+
+       vkGetDeviceQueue(vkdev, fam, n, &q);
+       return q;
+}
+
+VkQueue vk_getq(unsigned int flags)
+{
+       return vk_getq_fam(vk_find_qfamily(flags), 0);
+}
 
 int vk_create_rpass(void)
 {
@@ -557,10 +602,9 @@ static int create_surface(void)
 
 int choose_phys_dev(void)
 {
-       uint32_t i, num_pdev, num_qfam, score, best_score, best_dev;
+       uint32_t i, num_pdev, score, best_score, best_dev;
        VkPhysicalDevice *pdev;
        VkPhysicalDeviceProperties pdevprop;
-       VkQueueFamilyProperties *qfam;
        VkBool32 can_pres;
 
        vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
@@ -591,21 +635,12 @@ int choose_phys_dev(void)
        }
        vkpdev = pdev[best_dev];
 
+       if(qfam) free(qfam);
+
        vkGetPhysicalDeviceQueueFamilyProperties(vkpdev, &num_qfam, 0);
        qfam = malloc_nf(num_qfam * sizeof *qfam);
        vkGetPhysicalDeviceQueueFamilyProperties(vkpdev, &num_qfam, qfam);
 
-       vkqfam_idx = -1;
-       for(i=0; i<num_qfam; i++) {
-               vkGetPhysicalDeviceSurfaceSupportKHR(vkpdev, i, vksurf, &can_pres);
-               if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) {
-                       vkqfam_maxq = qfam[i].queueCount;
-                       vkqfam_idx = i;
-                       break;
-               }
-       }
-
-       free(qfam);
        free(pdev);
        choose_pixfmt();
        return 0;
@@ -646,7 +681,7 @@ static int create_device(void)
        }
 
        qinf.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
-       qinf.queueFamilyIndex = vkqfam_idx;
+       qinf.queueFamilyIndex = vk_find_qfamily(VKQ_GFX | VKQ_PRESENT);
        qinf.queueCount = 1;
        qinf.pQueuePriorities = &prio;
 
@@ -661,8 +696,6 @@ static int create_device(void)
                fprintf(stderr, "failed to create vulkan device\n");
                return -1;
        }
-
-       vkGetDeviceQueue(vkdev, vkqfam_idx, 0, &vkq);
        return 0;
 }
 
index 470f757..319fa99 100644 (file)
--- a/src/vk.h
+++ b/src/vk.h
@@ -10,6 +10,13 @@ enum {
        VKINIT_RAY              = 0x100
 };
 
+/* queue capability flags for vk_find_qfamily */
+enum {
+       VKQ_GFX                 = 1,
+       VKQ_COMPUTE             = 2,
+       VKQ_PRESENT             = 4
+};
+
 void vk_init_xwin(Display *dpy, Window win);
 
 int vk_init(unsigned int flags, unsigned int *usedflags);
@@ -17,6 +24,10 @@ void vk_cleanup(void);
 
 int vk_reshape(int xsz, int ysz);
 
+int vk_find_qfamily(unsigned int flags);
+VkQueue vk_getq_fam(int fam, int n);
+VkQueue vk_getq(unsigned int flags);
+
 int vk_create_rpass(void);
 void vk_free_rpass(int rp);
 void vk_rpass_colorbuf(int rp, int fmt, int n);