summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/amd/common/sid.h7
-rw-r--r--src/amd/vulkan/si_cmd_buffer.c56
2 files changed, 49 insertions, 14 deletions
diff --git a/src/amd/common/sid.h b/src/amd/common/sid.h
index be11c712cce..9d44d3cdbed 100644
--- a/src/amd/common/sid.h
+++ b/src/amd/common/sid.h
@@ -185,6 +185,7 @@
#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
@@ -198,6 +199,12 @@
#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.
diff --git a/src/amd/vulkan/si_cmd_buffer.c b/src/amd/vulkan/si_cmd_buffer.c
index 9be773468d5..591fc15f9b9 100644
--- a/src/amd/vulkan/si_cmd_buffer.c
+++ b/src/amd/vulkan/si_cmd_buffer.c
@@ -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 */
}
}