diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 06fb931d7..54c75ca4e 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -229,6 +229,13 @@ public:
         return true;
     }
 
+    bool HasUncommitedFlushes() {
+        if (uncommited_flushes) {
+            return true;
+        }
+        return false;
+    }
+
     void PopAsyncFlushes() {
         if (commited_flushes.empty()) {
             return;
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index a7e951433..2824ed707 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -405,7 +405,7 @@ void Maxwell3D::ProcessQueryGet() {
     switch (regs.query.query_get.operation) {
     case Regs::QueryOperation::Release:
         if (regs.query.query_get.fence == 1) {
-            rasterizer.SignalFence(regs.query.QueryAddress(), regs.query.query_sequence);
+            rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
         } else {
             StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
         }
@@ -487,7 +487,7 @@ void Maxwell3D::ProcessSyncPoint() {
     const u32 increment = regs.sync_info.increment.Value();
     [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
     if (increment) {
-        system.GPU().IncrementSyncPoint(sync_point);
+        rasterizer.SignalSyncPoint(sync_point);
     }
 }
 
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h
index 72ee50955..417cb113f 100644
--- a/src/video_core/fence_manager.h
+++ b/src/video_core/fence_manager.h
@@ -22,7 +22,11 @@ namespace VideoCommon {
 
 class FenceBase {
 public:
-    FenceBase(GPUVAddr address, u32 payload) : address{address}, payload{payload} {}
+    FenceBase(u32 payload, bool is_stubbed)
+        : address{}, payload{payload}, is_semaphore{false}, is_stubbed{is_stubbed} {}
+
+    FenceBase(GPUVAddr address, u32 payload, bool is_stubbed)
+        : address{address}, payload{payload}, is_semaphore{true}, is_stubbed{is_stubbed} {}
 
     constexpr GPUVAddr GetAddress() const {
         return address;
@@ -32,22 +36,49 @@ public:
         return payload;
     }
 
+    constexpr bool IsSemaphore() const {
+        return is_semaphore;
+    }
+
 private:
     GPUVAddr address;
     u32 payload;
+    bool is_semaphore;
+
+protected:
+    bool is_stubbed;
 };
 
 template <typename TFence, typename TTextureCache, typename TTBufferCache>
 class FenceManager {
 public:
-    void SignalFence(GPUVAddr addr, u32 value) {
+    void SignalSemaphore(GPUVAddr addr, u32 value) {
         TryReleasePendingFences();
+        bool should_flush = texture_cache.HasUncommitedFlushes();
+        should_flush |= buffer_cache.HasUncommitedFlushes();
         texture_cache.CommitAsyncFlushes();
         buffer_cache.CommitAsyncFlushes();
-        TFence new_fence = CreateFence(addr, value);
+        TFence new_fence = CreateFence(addr, value, !should_flush);
         fences.push(new_fence);
         QueueFence(new_fence);
-        rasterizer.FlushCommands();
+        if (should_flush) {
+            rasterizer.FlushCommands();
+        }
+        rasterizer.SyncGuestHost();
+    }
+
+    void SignalSyncPoint(u32 value) {
+        TryReleasePendingFences();
+        bool should_flush = texture_cache.HasUncommitedFlushes();
+        should_flush |= buffer_cache.HasUncommitedFlushes();
+        texture_cache.CommitAsyncFlushes();
+        buffer_cache.CommitAsyncFlushes();
+        TFence new_fence = CreateFence(value, !should_flush);
+        fences.push(new_fence);
+        QueueFence(new_fence);
+        if (should_flush) {
+            rasterizer.FlushCommands();
+        }
         rasterizer.SyncGuestHost();
     }
 
@@ -62,8 +93,12 @@ public:
             texture_cache.PopAsyncFlushes();
             buffer_cache.PopAsyncFlushes();
             auto& gpu{system.GPU()};
-            auto& memory_manager{gpu.MemoryManager()};
-            memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
+            if (current_fence->IsSemaphore()) {
+                auto& memory_manager{gpu.MemoryManager()};
+                memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
+            } else {
+                gpu.IncrementSyncPoint(current_fence->GetPayload());
+            }
             fences.pop();
         }
     }
@@ -74,7 +109,8 @@ protected:
         : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{
                                                                                     buffer_cache} {}
 
-    virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0;
+    virtual TFence CreateFence(u32 value, bool is_stubbed) = 0;
+    virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0;
     virtual void QueueFence(TFence& fence) = 0;
     virtual bool IsFenceSignaled(TFence& fence) = 0;
     virtual void WaitFence(TFence& fence) = 0;
@@ -96,8 +132,12 @@ private:
             texture_cache.PopAsyncFlushes();
             buffer_cache.PopAsyncFlushes();
             auto& gpu{system.GPU()};
-            auto& memory_manager{gpu.MemoryManager()};
-            memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
+            if (current_fence->IsSemaphore()) {
+                auto& memory_manager{gpu.MemoryManager()};
+                memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
+            } else {
+                gpu.IncrementSyncPoint(current_fence->GetPayload());
+            }
             fences.pop();
         }
     }
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index b49f15df2..4e9c8fb59 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -49,8 +49,11 @@ public:
     /// Records a GPU query and caches it
     virtual void Query(GPUVAddr gpu_addr, QueryType type, std::optional<u64> timestamp) = 0;
 
-    /// Signal a GPU based fence
-    virtual void SignalFence(GPUVAddr addr, u32 value) = 0;
+    /// Signal a GPU based semaphore as a fence
+    virtual void SignalSemaphore(GPUVAddr addr, u32 value) = 0;
+
+    /// Signal a GPU based syncpoint as a fence
+    virtual void SignalSyncPoint(u32 value) = 0;
 
     /// Release all pending fences.
     virtual void ReleaseFences() = 0;
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp
index 69dd3211b..579c03a1e 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp
@@ -8,17 +8,26 @@
 
 namespace OpenGL {
 
-GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload)
-    : VideoCommon::FenceBase(address, payload), sync_object{} {}
+GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed)
+    : VideoCommon::FenceBase(payload, is_stubbed), sync_object{} {}
+
+GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed)
+    : VideoCommon::FenceBase(address, payload, is_stubbed), sync_object{} {}
 
 GLInnerFence::~GLInnerFence() = default;
 
 void GLInnerFence::Queue() {
+    if (is_stubbed) {
+        return;
+    }
     ASSERT(sync_object.handle == 0);
     sync_object.Create();
 }
 
 bool GLInnerFence::IsSignaled() const {
+    if (is_stubbed) {
+        return true;
+    }
     ASSERT(sync_object.handle != 0);
     GLsizei length;
     GLint sync_status;
@@ -27,6 +36,9 @@ bool GLInnerFence::IsSignaled() const {
 }
 
 void GLInnerFence::Wait() {
+    if (is_stubbed) {
+        return;
+    }
     ASSERT(sync_object.handle != 0);
     while (glClientWaitSync(sync_object.handle, 0, 1000) == GL_TIMEOUT_EXPIRED)
         ;
@@ -36,8 +48,12 @@ FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::Rasteriz
                                TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache)
     : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {}
 
-Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) {
-    return std::make_shared<GLInnerFence>(addr, value);
+Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) {
+    return std::make_shared<GLInnerFence>(value, is_stubbed);
+}
+
+Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) {
+    return std::make_shared<GLInnerFence>(addr, value, is_stubbed);
 }
 
 void FenceManagerOpenGL::QueueFence(Fence& fence) {
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h
index b48d5eaa0..ba48d2f84 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.h
+++ b/src/video_core/renderer_opengl/gl_fence_manager.h
@@ -17,7 +17,8 @@ namespace OpenGL {
 
 class GLInnerFence : public VideoCommon::FenceBase {
 public:
-    GLInnerFence(GPUVAddr address, u32 payload);
+    GLInnerFence(u32 payload, bool is_stubbed);
+    GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed);
     ~GLInnerFence();
 
     void Queue();
@@ -39,7 +40,8 @@ public:
                        TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache);
 
 protected:
-    Fence CreateFence(GPUVAddr addr, u32 value) override;
+    Fence CreateFence(u32 value, bool is_stubbed) override;
+    Fence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) override;
     void QueueFence(Fence& fence) override;
     bool IsFenceSignaled(Fence& fence) override;
     void WaitFence(Fence& fence) override;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 88914828c..e52e5961f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -683,14 +683,23 @@ void RasterizerOpenGL::SyncGuestHost() {
     buffer_cache.SyncGuestHost();
 }
 
-void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) {
+void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) {
     auto& gpu{system.GPU()};
     if (!gpu.IsAsync()) {
         auto& memory_manager{gpu.MemoryManager()};
         memory_manager.Write<u32>(addr, value);
         return;
     }
-    fence_manager.SignalFence(addr, value);
+    fence_manager.SignalSemaphore(addr, value);
+}
+
+void RasterizerOpenGL::SignalSyncPoint(u32 value) {
+    auto& gpu{system.GPU()};
+    if (!gpu.IsAsync()) {
+        gpu.IncrementSyncPoint(value);
+        return;
+    }
+    fence_manager.SignalSyncPoint(value);
 }
 
 void RasterizerOpenGL::ReleaseFences() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 5c0f88e6f..15e9ff7d7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -71,7 +71,8 @@ public:
     void InvalidateRegion(VAddr addr, u64 size) override;
     void OnCPUWrite(VAddr addr, u64 size) override;
     void SyncGuestHost() override;
-    void SignalFence(GPUVAddr addr, u32 value) override;
+    void SignalSemaphore(GPUVAddr addr, u32 value) override;
+    void SignalSyncPoint(u32 value) override;
     void ReleaseFences() override;
     void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
     void FlushCommands() override;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 1d75a4766..507262c8f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -543,7 +543,7 @@ void RasterizerVulkan::SyncGuestHost() {
     buffer_cache.SyncGuestHost();
 }
 
-void RasterizerVulkan::SignalFence(GPUVAddr addr, u32 value) {
+void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) {
     auto& gpu{system.GPU()};
     auto& memory_manager{gpu.MemoryManager()};
     memory_manager.Write<u32>(addr, value);
@@ -553,7 +553,19 @@ void RasterizerVulkan::SignalFence(GPUVAddr addr, u32 value) {
         memory_manager.Write<u32>(addr, value);
         return;
     }
-    fence_manager.SignalFence(addr, value);
+    fence_manager.SignalSemaphore(addr, value);
+    */
+}
+
+void RasterizerVulkan::SignalSyncPoint(u32 value) {
+    auto& gpu{system.GPU()};
+    gpu.IncrementSyncPoint(value);
+    /*
+    if (!gpu.IsAsync()) {
+        gpu.IncrementSyncPoint(value);
+        return;
+    }
+    fence_manager.SignalSyncPoint(value);
     */
 }
 
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 08a9af401..145bdf899 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -122,7 +122,8 @@ public:
     void InvalidateRegion(VAddr addr, u64 size) override;
     void OnCPUWrite(VAddr addr, u64 size) override;
     void SyncGuestHost() override;
-    void SignalFence(GPUVAddr addr, u32 value) override;
+    void SignalSemaphore(GPUVAddr addr, u32 value) override;
+    void SignalSyncPoint(u32 value) override;
     void ReleaseFences() override;
     void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
     void FlushCommands() override;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index e1a1edbd2..f3ca1ffd1 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -337,6 +337,13 @@ public:
         uncommited_flushes.reset();
     }
 
+    bool HasUncommitedFlushes() {
+        if (uncommited_flushes) {
+            return true;
+        }
+        return false;
+    }
+
     bool ShouldWaitAsyncFlushes() {
         if (commited_flushes.empty()) {
             return false;