radv: add support for emitting PS_DONE/CS_DONE on GFX6-8
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 22 Jan 2021 15:41:39 +0000 (16:41 +0100)
committerMarge Bot <eric+marge@anholt.net>
Tue, 26 Jan 2021 09:26:58 +0000 (09:26 +0000)
On GFX6, EOS events are always emitted with EVENT_WRITE_EOS.
On GFX7+, EOS events are emitted with EVENT_WRITE_EOS on the
graphics queue, and with RELEASE_MEM on the compute queue.

Fixes: 9c65f1f1111 ("radv: synchronize Cmd{Set,Write}Event() using PS_DONE/CS_DONE events")
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8710>

src/amd/common/sid.h
src/amd/vulkan/si_cmd_buffer.c

index be11c71..9d44d3c 100644 (file)
 #define PKT3_COND_WRITE                        0x45
 #define PKT3_EVENT_WRITE                       0x46
 #define PKT3_EVENT_WRITE_EOP                   0x47 /* not on GFX9 */
+#define PKT3_EVENT_WRITE_EOS                   0x48 /* not on GFX9 */
 #define EOP_DST_SEL(x)                         ((x) << 16)
 #define EOP_DST_SEL_MEM                        0
 #define EOP_DST_SEL_TC_L2                      1
 #define EOP_DATA_SEL_TIMESTAMP                 3
 #define EOP_DATA_SEL_GDS                       5
 #define EOP_DATA_GDS(dw_offset, num_dwords)    ((dw_offset) | ((unsigned)(num_dwords) << 16))
+
+#define EOS_DATA_SEL(x)                        ((x) << 29)
+#define EOS_DATA_SEL_APPEND_COUNT              0
+#define EOS_DATA_SEL_GDS                       1
+#define EOS_DATA_SEL_VALUE_32BIT               2
+
 /* CP DMA bug: Any use of CP_DMA.DST_SEL=TC must be avoided when EOS packets
  * are used. Use DST_SEL=MC instead. For prefetch, use SRC_SEL=TC and
  * DST_SEL=MC. Only CIK chips are affected.
index 9be7734..591fc15 100644 (file)
@@ -989,26 +989,54 @@ void si_cs_emit_write_event_eop(struct radeon_cmdbuf *cs,
                if (!is_gfx8_mec)
                        radeon_emit(cs, 0); /* unused */
        } else {
-               if (chip_class == GFX7 ||
-                   chip_class == GFX8) {
-                       /* Two EOP events are required to make all engines go idle
-                        * (and optional cache flushes executed) before the timestamp
-                        * is written.
-                        */
+               /* On GFX6, EOS events are always emitted with EVENT_WRITE_EOS.
+                * On GFX7+, EOS events are emitted with EVENT_WRITE_EOS on
+                * the graphics queue, and with RELEASE_MEM on the compute
+                * queue.
+                */
+               if (event == V_028B9C_CS_DONE || event == V_028B9C_PS_DONE) {
+                       assert(event_flags == 0 &&
+                              dst_sel == EOP_DST_SEL_MEM &&
+                              data_sel == EOP_DATA_SEL_VALUE_32BIT);
+
+                       if (is_mec) {
+                               radeon_emit(cs, PKT3(PKT3_RELEASE_MEM, 5, false));
+                               radeon_emit(cs, op);
+                               radeon_emit(cs, sel);
+                               radeon_emit(cs, va);            /* address lo */
+                               radeon_emit(cs, va >> 32);      /* address hi */
+                               radeon_emit(cs, new_fence);     /* immediate data lo */
+                               radeon_emit(cs, 0);             /* immediate data hi */
+                       } else {
+                               radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOS, 3, false));
+                               radeon_emit(cs, op);
+                               radeon_emit(cs, va);
+                               radeon_emit(cs, ((va >> 32) & 0xffff) |
+                                               EOS_DATA_SEL(EOS_DATA_SEL_VALUE_32BIT));
+                               radeon_emit(cs, new_fence);
+                       }
+               } else {
+                       if (chip_class == GFX7 ||
+                           chip_class == GFX8) {
+                               /* Two EOP events are required to make all
+                                * engines go idle (and optional cache flushes
+                                * executed) before the timestamp is written.
+                                */
+                               radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOP, 4, false));
+                               radeon_emit(cs, op);
+                               radeon_emit(cs, va);
+                               radeon_emit(cs, ((va >> 32) & 0xffff) | sel);
+                               radeon_emit(cs, 0); /* immediate data */
+                               radeon_emit(cs, 0); /* unused */
+                       }
+
                        radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOP, 4, false));
                        radeon_emit(cs, op);
                        radeon_emit(cs, va);
                        radeon_emit(cs, ((va >> 32) & 0xffff) | sel);
-                       radeon_emit(cs, 0); /* immediate data */
+                       radeon_emit(cs, new_fence); /* immediate data */
                        radeon_emit(cs, 0); /* unused */
                }
-
-               radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOP, 4, false));
-               radeon_emit(cs, op);
-               radeon_emit(cs, va);
-               radeon_emit(cs, ((va >> 32) & 0xffff) | sel);
-               radeon_emit(cs, new_fence); /* immediate data */
-               radeon_emit(cs, 0); /* unused */
        }
 }