spirv: implement MakePointerAvailable/MakePointerVisible for OpCopyMemory
[mesa.git] / src / compiler / spirv / vtn_variables.c
index fa78f80459483930b5f3605b4025ff440c4e6177..6de4ceffb82ae2e63053f77490e3a02ec4dbe8b7 100644 (file)
@@ -2500,6 +2500,30 @@ vtn_mode_to_memory_semantics(enum vtn_variable_mode mode)
    }
 }
 
+static void
+vtn_emit_make_visible_barrier(struct vtn_builder *b, SpvMemoryAccessMask access,
+                              SpvScope scope, enum vtn_variable_mode mode)
+{
+   if (!(access & SpvMemoryAccessMakePointerVisibleMask))
+      return;
+
+   vtn_emit_memory_barrier(b, scope, SpvMemorySemanticsMakeVisibleMask |
+                                     SpvMemorySemanticsAcquireMask |
+                                     vtn_mode_to_memory_semantics(mode));
+}
+
+static void
+vtn_emit_make_available_barrier(struct vtn_builder *b, SpvMemoryAccessMask access,
+                                SpvScope scope, enum vtn_variable_mode mode)
+{
+   if (!(access & SpvMemoryAccessMakePointerAvailableMask))
+      return;
+
+   vtn_emit_memory_barrier(b, scope, SpvMemorySemanticsMakeAvailableMask |
+                                     SpvMemorySemanticsReleaseMask |
+                                     vtn_mode_to_memory_semantics(mode));
+}
+
 void
 vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
                      const uint32_t *w, unsigned count)
@@ -2602,7 +2626,22 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
 
       vtn_assert_types_equal(b, opcode, dest->type->deref, src->type->deref);
 
+      unsigned idx = 3, dest_alignment, src_alignment;
+      SpvMemoryAccessMask dest_access, src_access;
+      SpvScope dest_scope, src_scope;
+      vtn_get_mem_operands(b, w, count, &idx, &dest_access, &dest_alignment,
+                           &dest_scope, &src_scope);
+      if (!vtn_get_mem_operands(b, w, count, &idx, &src_access, &src_alignment,
+                                NULL, &src_scope)) {
+         src_alignment = dest_alignment;
+         src_access = dest_access;
+      }
+
+      vtn_emit_make_visible_barrier(b, src_access, src_scope, src->pointer->mode);
+
       vtn_variable_copy(b, dest->pointer, src->pointer);
+
+      vtn_emit_make_available_barrier(b, dest_access, dest_scope, dest->pointer->mode);
       break;
    }
 
@@ -2617,12 +2656,8 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
       SpvMemoryAccessMask access;
       SpvScope scope;
       vtn_get_mem_operands(b, w, count, &idx, &access, &alignment, NULL, &scope);
-      if (access & SpvMemoryAccessMakePointerVisibleMask) {
-         SpvMemorySemanticsMask semantics =
-            SpvMemorySemanticsMakeVisibleMask |
-            vtn_mode_to_memory_semantics(src->mode);
-         vtn_emit_memory_barrier(b, scope, semantics);
-      }
+
+      vtn_emit_make_visible_barrier(b, access, scope, src->mode);
 
       vtn_push_ssa_value(b, w[2], vtn_variable_load(b, src));
       break;
@@ -2666,12 +2701,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
       struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]);
       vtn_variable_store(b, src, dest);
 
-      if (access & SpvMemoryAccessMakePointerAvailableMask) {
-         SpvMemorySemanticsMask semantics =
-            SpvMemorySemanticsMakeAvailableMask |
-            vtn_mode_to_memory_semantics(dest->mode);
-         vtn_emit_memory_barrier(b, scope, semantics);
-      }
+      vtn_emit_make_available_barrier(b, access, scope, dest->mode);
       break;
    }