diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 652329c38f..f4c1bd9790 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -80,7 +80,6 @@ constexpr std::array REQUIRED_EXTENSIONS{
 
     // Core in 1.2, but required due to use of extension methods,
     // and well-supported by drivers
-    VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME,
     VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
     VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
 #ifdef _WIN32
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 2ad98dcfe5..af79ffd61e 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -180,7 +180,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkGetQueryPoolResults);
     X(vkGetPipelineExecutablePropertiesKHR);
     X(vkGetPipelineExecutableStatisticsKHR);
-    X(vkGetSemaphoreCounterValueKHR);
+    X(vkGetSemaphoreCounterValue);
     X(vkMapMemory);
     X(vkQueueSubmit);
     X(vkResetFences);
@@ -191,7 +191,14 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkUpdateDescriptorSetWithTemplateKHR);
     X(vkUpdateDescriptorSets);
     X(vkWaitForFences);
-    X(vkWaitSemaphoresKHR);
+    X(vkWaitSemaphores);
+
+    // Support for timeline semaphores is mandatory in Vulkan 1.2
+    if (!dld.vkGetSemaphoreCounterValue) {
+        Proc(dld.vkGetSemaphoreCounterValue, dld, "vkGetSemaphoreCounterValue", device);
+        Proc(dld.vkWaitForFences, dld, "vkWaitForFencesKHR", device);
+        Proc(dld.vkWaitSemaphores, dld, "vkWaitSemaphoresKHR", device);
+    }
 #undef X
 }
 
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 1b3f493bde..fb6c59f60c 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -297,7 +297,7 @@ struct DeviceDispatch : InstanceDispatch {
     PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{};
     PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{};
     PFN_vkGetQueryPoolResults vkGetQueryPoolResults{};
-    PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR{};
+    PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{};
     PFN_vkMapMemory vkMapMemory{};
     PFN_vkQueueSubmit vkQueueSubmit{};
     PFN_vkResetFences vkResetFences{};
@@ -308,7 +308,7 @@ struct DeviceDispatch : InstanceDispatch {
     PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR{};
     PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
     PFN_vkWaitForFences vkWaitForFences{};
-    PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR{};
+    PFN_vkWaitSemaphores vkWaitSemaphores{};
 };
 
 /// Loads instance agnostic function pointers.
@@ -766,7 +766,7 @@ public:
 
     [[nodiscard]] u64 GetCounter() const {
         u64 value;
-        Check(dld->vkGetSemaphoreCounterValueKHR(owner, handle, &value));
+        Check(dld->vkGetSemaphoreCounterValue(owner, handle, &value));
         return value;
     }
 
@@ -778,15 +778,15 @@ public:
      * @return        True on successful wait, false on timeout
      */
     bool Wait(u64 value, u64 timeout = std::numeric_limits<u64>::max()) const {
-        const VkSemaphoreWaitInfoKHR wait_info{
-            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR,
+        const VkSemaphoreWaitInfo wait_info{
+            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
             .pNext = nullptr,
             .flags = 0,
             .semaphoreCount = 1,
             .pSemaphores = &handle,
             .pValues = &value,
         };
-        const VkResult result = dld->vkWaitSemaphoresKHR(owner, &wait_info, timeout);
+        const VkResult result = dld->vkWaitSemaphores(owner, &wait_info, timeout);
         switch (result) {
         case VK_SUCCESS:
             return true;