break;
       }
 
-      case VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA: {
-         const struct wsi_memory_allocate_info *wsi_info = (void *)ext;
-         if (wsi_info->implicit_sync) {
-            /* We need to set the WRITE flag on window system buffers so that
-             * GEM will know we're writing to them and synchronize uses on
-             * other rings (eg if the display server uses the blitter ring).
-             */
-            alloc_flags |= ANV_BO_ALLOC_IMPLICIT_SYNC |
-                           ANV_BO_ALLOC_IMPLICIT_WRITE;
-         }
-         break;
-      }
-
       default:
          anv_debug_ignored_stype(ext->sType);
          break;
 
                  const VkSemaphore *out_semaphores,
                  const uint64_t *out_values,
                  uint32_t num_out_semaphores,
+                 struct anv_bo *wsi_signal_bo,
                  VkFence _fence)
 {
    ANV_FROM_HANDLE(anv_fence, fence, _fence);
       }
    }
 
+   if (wsi_signal_bo) {
+      result = anv_queue_submit_add_fence_bo(submit, wsi_signal_bo, true /* signal */);
+      if (result != VK_SUCCESS)
+         goto error;
+   }
+
    if (fence) {
       /* Under most circumstances, out fences won't be temporary.  However,
        * the spec does allow it for opaque_fd.  From the Vulkan 1.0.53 spec:
        * come up with something more efficient but this shouldn't be a
        * common case.
        */
-      result = anv_queue_submit(queue, NULL, NULL, NULL, 0, NULL, NULL, 0, fence);
+      result = anv_queue_submit(queue, NULL, NULL, NULL, 0, NULL, NULL, 0,
+                                NULL, fence);
       goto out;
    }
 
       /* Fence for this submit.  NULL for all but the last one */
       VkFence submit_fence = (i == submitCount - 1) ? fence : VK_NULL_HANDLE;
 
+      const struct wsi_memory_signal_submit_info *mem_signal_info =
+         vk_find_struct_const(pSubmits[i].pNext,
+                              WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA);
+      struct anv_bo *wsi_signal_bo =
+         mem_signal_info && mem_signal_info->memory != VK_NULL_HANDLE ?
+         anv_device_memory_from_handle(mem_signal_info->memory)->bo : NULL;
+
       const VkTimelineSemaphoreSubmitInfoKHR *timeline_info =
          vk_find_struct_const(pSubmits[i].pNext,
                               TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR);
                                    pSubmits[i].pSignalSemaphores,
                                    signal_values,
                                    pSubmits[i].signalSemaphoreCount,
+                                   wsi_signal_bo,
                                    submit_fence);
          if (result != VK_SUCCESS)
             goto out;
          result = anv_queue_submit(queue, cmd_buffer,
                                    in_semaphores, in_values, num_in_semaphores,
                                    out_semaphores, out_values, num_out_semaphores,
-                                   execbuf_fence);
+                                   wsi_signal_bo, execbuf_fence);
          if (result != VK_SUCCESS)
             goto out;
       }