From 8c7d5a01f9975baa11f84d71bb0d6fadd719c4ad Mon Sep 17 00:00:00 2001 From: Shane Xiao Date: Fri, 13 Sep 2024 16:04:09 +0800 Subject: [PATCH] wsl/hsakmt: Add no pcie atomic support for dispatch packet This patch adds no pcie atomic support. This patch uses cpu to update cmd queue completion signal to resolve potential contention issue, and replaces ATOMIC_MEM with WRITE_DATA packet to update ring_index. Signed-off-by: Shane Xiao Reviewed-by: Aaron Liu Reviewed-by: Longlong Yao Reviewed-by: Flora Cui Part-of: --- inc/wddm/queue.h | 2 ++ wddm/queue.cpp | 33 +++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/inc/wddm/queue.h b/inc/wddm/queue.h index 34f9feaee8..1324aa31a7 100644 --- a/inc/wddm/queue.h +++ b/inc/wddm/queue.h @@ -207,6 +207,8 @@ private: uint64_t cmdbuf_aql_frame_write_index; uint32_t cmdbuf_aql_frame_size; + uint64_t *signal_addr_; + bool platform_atomic_support_; bool needs_barrier; bool ready_to_submit; diff --git a/wddm/queue.cpp b/wddm/queue.cpp index ec9ad4305a..0635fb46c8 100644 --- a/wddm/queue.cpp +++ b/wddm/queue.cpp @@ -251,6 +251,8 @@ ComputeQueue::ComputeQueue(WDDMDevice *device, cmdbuf_aql_frame_size(0), needs_barrier(true), ready_to_submit(false), + platform_atomic_support_(false), + signal_addr_(NULL), thread_stop_(false), scratch_waves_(device->MaxScratchSlotsPerCu() * device->ComputeUnitCount()), scratch_size_per_wave_(0), @@ -548,6 +550,7 @@ hsa_status_t ComputeQueue::Init(void) { ib_start_addr = cmdbuf_addr; cmdbuf_aql_frame_size = device->GetAqlFrameSize(); + platform_atomic_support_ = device->SupportPlatformAtomic(); return ret; } @@ -704,13 +707,19 @@ ComputeQueue::KernelDispatchAqlToPm4(char *cpu, hsa_kernel_dispatch_packet_t *pa uint64_t *signal_addr = (uint64_t *)&signal->value; debug_print("signal value=%" PRIx64 "\n", signal->value); - i += cmd_util.BuildAtomicMem(signal_addr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i, cache_policy__mec_atomic_mem__bypass, -1); + if (platform_atomic_support_) + i += cmd_util.BuildAtomicMem(signal_addr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i, cache_policy__mec_atomic_mem__bypass, -1); + else + signal_addr_ = signal_addr; } // The ring_rptr is used to record pm4 queue rptr value, // dispatch readptr position, this is used to share rptr with // aql queue. - i += cmd_util.BuildAtomicMem((uint64_t *)ring_rptr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i); + if (platform_atomic_support_) + i += cmd_util.BuildAtomicMem((uint64_t *)ring_rptr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i); + else + i += cmd_util.BuildWriteData64Command(cpu + i, (uint64_t *)ring_rptr, cmdbuf_aql_frame_write_index + 1); ib_size = i; cmdbuf_aql_frame_write_index++; @@ -786,13 +795,19 @@ ComputeQueue::BarrierGenericAqlToPm4(char *cpu, hsa_barrier_and_packet_t *packet // flush cache i += cmd_util.BuildAcquireMem(major, cpu + i); - i += cmd_util.BuildAtomicMem(signal_addr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i, cache_policy__mec_atomic_mem__bypass, -1); + if (platform_atomic_support_) + i += cmd_util.BuildAtomicMem(signal_addr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i, cache_policy__mec_atomic_mem__bypass, -1); + else + signal_addr_ = signal_addr; } // The ring_rptr is used to record pm4 queue rptr value, // dispatch readptr position, this is used to share rptr with // aql queue. - i += cmd_util.BuildAtomicMem((uint64_t *)ring_rptr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i); + if (platform_atomic_support_) + i += cmd_util.BuildAtomicMem((uint64_t *)ring_rptr, TC_OP_ATOMIC_ADD_RTN_64, cpu + i); + else + i += cmd_util.BuildWriteData64Command(cpu + i, (uint64_t *)ring_rptr, cmdbuf_aql_frame_write_index + 1); ib_size = i; cmdbuf_aql_frame_write_index++; @@ -944,6 +959,16 @@ hsa_status_t ComputeQueue::Process(void) { if (ret != HSA_STATUS_SUCCESS) return ret; + // CPU wait for GPU fence, and cpu update the signal. + if (!platform_atomic_support_ && signal_addr_) { + // CPU wait for GPU fence + if (!device->CpuWait(&syncobj, &cmdbuf_aql_frame_write_index, 1, false)) + return HSA_STATUS_ERROR; + //CPU update completional signal + atomic::Decrement(signal_addr_); + signal_addr_ = NULL; + } + ready_to_submit = false; debug_print("done %p wptr=%" PRIx64 " rptr=%" PRIx64 "\n",