瀏覽代碼

Improve physical device selection

Kajetan Johannes Hammerle 2 月之前
父節點
當前提交
d5b33f747d
共有 1 個文件被更改,包括 65 次插入65 次删除
  1. 65 65
      src/VulkanWrapper.c

+ 65 - 65
src/VulkanWrapper.c

@@ -17,6 +17,11 @@ typedef struct {
     VkFramebuffer* framebuffers;
 } Swapchain;
 
+typedef struct {
+    VkPhysicalDevice handle;
+    u32 graphicsFamily;
+} PhysicalDevice;
+
 typedef struct {
     // basic setup
     VkInstance instance;
@@ -26,8 +31,7 @@ typedef struct {
     VkDebugReportCallbackEXT debugReportCallback;
 #endif
     // render setup
-    u32 graphicsFamily;
-    VkPhysicalDevice physicalDevice;
+    PhysicalDevice physicalDevice;
     VkDevice device;
     VkQueue graphicsQueue;
     VkSemaphore semaphore;
@@ -196,74 +200,68 @@ static void destroyDebugReportCallback() {
 }
 #endif
 
-static bool choosePhysicalDevice(VkPhysicalDevice* devices, u32 amount) {
-    VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &amount, devices));
-    int bestPoints = 0;
-    LOG_INFO("Found %u devices", amount);
-    for(u32 i = 0; i < amount; i++) {
-        int points = 0;
-        VkPhysicalDeviceProperties p;
-        vkGetPhysicalDeviceProperties(devices[i], &p);
-        if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
-            points += 100;
-        } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
-            points += 50;
-        } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
-            points += 20;
-        }
-        if(points > bestPoints) {
-            bestPoints = points;
-            vk.physicalDevice = devices[i];
-            LOG_INFO("Best Device: %s", p.deviceName);
+static u32 findQueueFamilies(VkPhysicalDevice pd, VkQueueFlags flags) {
+    VkQueueFamilyProperties properties[32];
+    u32 count = ARRAY_LENGTH(properties);
+    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, properties);
+    for(u32 i = 0; i < count; i++) {
+        if((properties[i].queueFlags & flags) == flags) {
+            return i;
         }
     }
-    return bestPoints == 0;
+    return (u32)-1;
 }
 
-static bool initPhysicalDevice() {
-    u32 deviceCount = 0;
-    VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &deviceCount, nullptr));
-    if(deviceCount == 0) {
-        LOG_ERROR("No physical device was found");
-        return true;
+static int getDevicePoints(PhysicalDevice pd) {
+    int points = 0;
+    VkPhysicalDeviceProperties p;
+    vkGetPhysicalDeviceProperties(pd.handle, &p);
+    LOG_INFO("Checking '%s'", p.deviceName);
+    switch(p.deviceType) {
+        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: points += 100; break;
+        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: points += 50; break;
+        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: points += 20; break;
+        default: break;
+    }
+    pd.graphicsFamily = findQueueFamilies(pd.handle, VK_QUEUE_GRAPHICS_BIT);
+    if(pd.graphicsFamily == (u32)-1) {
+        LOG_INFO("> ... has no graphics family");
+        points = -1;
     }
-    VkPhysicalDevice* devices =
-        coreAllocate(sizeof(VkPhysicalDevice) * deviceCount);
-    bool r = choosePhysicalDevice(devices, deviceCount);
-    coreFree(devices);
-    return r;
+    LOG_INFO("> Final points: %d", points);
+    return points;
 }
 
-static u32 findQueueFamilies(VkPhysicalDevice pd, VkQueueFlags flags) {
-    u32 count = 0;
-    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, nullptr);
-    VkQueueFamilyProperties* properties =
-        coreAllocate(sizeof(VkQueueFamilyProperties) * count);
-    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, properties);
-    for(u32 i = 0; i < count; i++) {
-        if(properties[i].queueCount != 0 &&
-           (properties[i].queueFlags & flags) == flags) {
-            coreFree(properties);
-            return i;
+static bool initPhysicalDevice() {
+    VkPhysicalDevice devices[32];
+    u32 c = ARRAY_LENGTH(devices);
+    VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &c, devices));
+    LOG_INFO("Found %u physical devices", c);
+    int bestPoints = 0;
+    for(u32 i = 0; i < c; i++) {
+        PhysicalDevice pd = {.handle = devices[i]};
+        int points = getDevicePoints(pd);
+        if(points > bestPoints) {
+            bestPoints = points;
+            vk.physicalDevice = pd;
         }
     }
-    coreFree(properties);
-    return (u32)-1;
+    if(bestPoints == 0) {
+        LOG_ERROR("No matching physical device was found");
+        return true;
+    }
+    VkPhysicalDeviceProperties p;
+    vkGetPhysicalDeviceProperties(vk.physicalDevice.handle, &p);
+    LOG_INFO("Best Device: %s", p.deviceName);
+    return false;
 }
 
 static bool initDevice() {
     VkPhysicalDeviceFeatures deviceFeatures = {0};
-    vkGetPhysicalDeviceFeatures(vk.physicalDevice, &deviceFeatures);
-
-    vk.graphicsFamily =
-        findQueueFamilies(vk.physicalDevice, VK_QUEUE_GRAPHICS_BIT);
-    if(vk.graphicsFamily == (u32)-1) {
-        LOG_ERROR("Cannot find queue family");
-        return true;
-    }
+    vkGetPhysicalDeviceFeatures(vk.physicalDevice.handle, &deviceFeatures);
     VkDeviceQueueCreateInfo dqInfo = {
         .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
-        .queueFamilyIndex = vk.graphicsFamily,
+        .queueFamilyIndex = vk.physicalDevice.graphicsFamily,
         .queueCount = 1,
         .pQueuePriorities = (float[]){1.0f}};
     VkDeviceCreateInfo deviceCreateInfo = {
@@ -275,8 +273,9 @@ static bool initDevice() {
             (const char*[]){VK_KHR_SWAPCHAIN_EXTENSION_NAME},
         .pEnabledFeatures = &deviceFeatures};
     VK_ASSERT(vkCreateDevice(
-        vk.physicalDevice, &deviceCreateInfo, nullptr, &vk.device));
-    vkGetDeviceQueue(vk.device, vk.graphicsFamily, 0, &vk.graphicsQueue);
+        vk.physicalDevice.handle, &deviceCreateInfo, nullptr, &vk.device));
+    vkGetDeviceQueue(
+        vk.device, vk.physicalDevice.graphicsFamily, 0, &vk.graphicsQueue);
     if(vk.graphicsQueue == VK_NULL_HANDLE) {
         LOG_ERROR("Cannot get device graphics queue");
         return true;
@@ -303,10 +302,10 @@ static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
 static bool getSurfaceFormat(VkSurfaceFormatKHR* sf) {
     u32 c = 0;
     VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(
-        vk.physicalDevice, vk.surface, &c, nullptr));
+        vk.physicalDevice.handle, vk.surface, &c, nullptr));
     VkSurfaceFormatKHR* formats = coreAllocate(sizeof(VkSurfaceFormatKHR) * c);
     VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(
-        vk.physicalDevice, vk.surface, &c, formats));
+        vk.physicalDevice.handle, vk.surface, &c, formats));
     for(u32 i = 0; i < c; i++) {
         if(formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
            formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
@@ -323,10 +322,10 @@ static bool getSurfaceFormat(VkSurfaceFormatKHR* sf) {
 static bool getPresentMode(VkPresentModeKHR* pm) {
     u32 c = 0;
     VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(
-        vk.physicalDevice, vk.surface, &c, nullptr));
+        vk.physicalDevice.handle, vk.surface, &c, nullptr));
     VkPresentModeKHR* modes = coreAllocate(sizeof(VkPresentModeKHR) * c);
     VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(
-        vk.physicalDevice, vk.surface, &c, modes));
+        vk.physicalDevice.handle, vk.surface, &c, modes));
     for(u32 i = 0; i < c; i++) {
         if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
             *pm = modes[i];
@@ -342,7 +341,7 @@ static bool getPresentMode(VkPresentModeKHR* pm) {
 static bool initSwapchain() {
     VkSurfaceCapabilitiesKHR caps = {0};
     VK_ASSERT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
-        vk.physicalDevice, vk.surface, &caps));
+        vk.physicalDevice.handle, vk.surface, &caps));
     VkSurfaceFormatKHR sf = {0};
     if(getSurfaceFormat(&sf)) {
         return true;
@@ -364,7 +363,7 @@ static bool initSwapchain() {
                       VK_IMAGE_USAGE_TRANSFER_DST_BIT,
         .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
         .queueFamilyIndexCount = 1,
-        .pQueueFamilyIndices = &vk.graphicsFamily,
+        .pQueueFamilyIndices = &vk.physicalDevice.graphicsFamily,
         .preTransform = caps.currentTransform,
         .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
         .presentMode = pm,
@@ -432,7 +431,8 @@ static void destroySemaphore(VkSemaphore s) {
 static bool checkPresentationSupport() {
     VkBool32 b = false;
     VK_ASSERT(vkGetPhysicalDeviceSurfaceSupportKHR(
-        vk.physicalDevice, vk.graphicsFamily, vk.surface, &b));
+        vk.physicalDevice.handle, vk.physicalDevice.graphicsFamily, vk.surface,
+        &b));
     if(!b) {
         LOG_ERROR("Presentation is not supported");
         return true;
@@ -443,7 +443,7 @@ static bool checkPresentationSupport() {
 static bool initCommandBuffers() {
     VkCommandPoolCreateInfo info = {
         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
-        .queueFamilyIndex = vk.graphicsFamily};
+        .queueFamilyIndex = vk.physicalDevice.graphicsFamily};
     VK_ASSERT(vkCreateCommandPool(
         vk.device, &info, nullptr, &vk.swapchain.commandPool));
     vk.swapchain.commandsBuffers =