loader: Remove duplicate search paths on posix

Windows platforms remove duplicate search paths due to registry keys
that are not device-specific but need to be searched. For the most
part, mac and linux do not need to do that. But if duplicate paths
crop up on a posix platform, it can cause the same device showing up
twice in the vkEnumeratePhysicalDevices results. There may be other
places it causes unexpected results as well.

VkPhysicalDeviceIDProperties.deviceUUID can be used later to tell that
the two entries are actually the same device and not a multi-GPU
system, but finding the root cause at that point is going to be very
difficult.
diff --git a/loader/loader.c b/loader/loader.c
index 143be13..b84935b 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -3858,6 +3858,31 @@
 #endif
     }
 
+    // Remove duplicate paths, or it would result in duplicate extensions, duplicate devices, etc.
+    // This uses minimal memory, but is O(N^2) on the number of paths. Expect only a few paths.
+    char path_sep_str[2] = { PATH_SEPARATOR, '\0' };
+    size_t search_path_updated_size = strlen(search_path);
+    for (size_t first = 0; first < search_path_updated_size - 1; ) {
+        size_t first_end = first + 1;
+        first_end += strcspn(&search_path[first_end], path_sep_str);
+        for (size_t second = first_end + 1; second < search_path_updated_size; ) {
+            size_t second_end = second + 1;
+            second_end += strcspn(&search_path[second_end], path_sep_str);
+            if (first_end - first == second_end - second && !strncmp(&search_path[first], &search_path[second], second_end - second)) {
+                // Found duplicate. Include PATH_SEPARATOR in second_end, then erase it from search_path.
+                if (search_path[second_end] == PATH_SEPARATOR) {
+                    second_end++;
+                }
+                memmove(&search_path[second], &search_path[second_end], search_path_updated_size - second_end + 1);
+                search_path_updated_size -= second_end - second;
+            } else {
+                second = second_end + 1;
+            }
+        }
+        first = first_end + 1;
+    }
+    search_path_size = search_path_updated_size;
+
     // Print out the paths being searched if debugging is enabled
     if (search_path_size > 0) {
         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,