2023-10-26 20:06:18 +00:00
|
|
|
/* Copyright (c) 2008 - 2023 Advanced Micro Devices, Inc.
|
2020-02-04 09:26:14 -08:00
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE. */
|
2016-07-21 12:41:26 -04:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2020-06-04 01:16:31 -04:00
|
|
|
#include "platform/commandqueue.hpp"
|
2021-01-19 18:06:08 -05:00
|
|
|
#include "rocdefs.hpp"
|
2016-07-21 12:41:26 -04:00
|
|
|
#include "rocdevice.hpp"
|
|
|
|
|
#include "utils/util.hpp"
|
2022-08-05 05:42:39 +00:00
|
|
|
#include "hsa/hsa.h"
|
|
|
|
|
#include "hsa/hsa_ext_image.h"
|
|
|
|
|
#include "hsa/hsa_ext_amd.h"
|
2016-07-21 12:41:26 -04:00
|
|
|
#include "rocprintf.hpp"
|
2022-08-05 05:42:39 +00:00
|
|
|
#include "hsa/hsa_ven_amd_aqlprofile.h"
|
2018-06-12 16:17:29 -04:00
|
|
|
#include "rocsched.hpp"
|
2016-07-21 12:41:26 -04:00
|
|
|
|
|
|
|
|
namespace roc {
|
|
|
|
|
class Device;
|
|
|
|
|
class Memory;
|
2021-06-18 17:07:40 -04:00
|
|
|
struct ProfilingSignal;
|
2016-07-21 12:41:26 -04:00
|
|
|
class Timestamp;
|
|
|
|
|
|
2020-09-25 12:56:48 -04:00
|
|
|
// Initial HSA signal value
|
2021-02-17 14:48:08 -05:00
|
|
|
constexpr static hsa_signal_value_t kInitSignalValueOne = 1;
|
2020-09-25 12:56:48 -04:00
|
|
|
|
2021-02-17 14:48:08 -05:00
|
|
|
// Timeouts for HSA signal wait
|
2021-06-09 00:08:02 -07:00
|
|
|
constexpr static uint64_t kTimeout100us = 100 * K;
|
2021-02-17 14:48:08 -05:00
|
|
|
constexpr static uint64_t kUnlimitedWait = std::numeric_limits<uint64_t>::max();
|
2020-09-25 12:56:48 -04:00
|
|
|
|
2022-10-17 14:31:24 -04:00
|
|
|
// Active wait time out incase same sdma engine is used again,
|
|
|
|
|
// then just wait instead of adding dependency wait signal.
|
2023-08-07 13:46:02 -04:00
|
|
|
constexpr static uint64_t kForcedTimeout10us = 10;
|
2022-10-17 14:31:24 -04:00
|
|
|
|
2021-06-09 00:08:02 -07:00
|
|
|
template <bool active_wait_timeout = false>
|
2022-12-01 13:32:35 +00:00
|
|
|
inline bool WaitForSignal(hsa_signal_t signal, bool active_wait = false, bool forced_wait = false) {
|
2021-06-09 00:08:02 -07:00
|
|
|
if (hsa_signal_load_relaxed(signal) > 0) {
|
2021-07-19 15:05:24 -04:00
|
|
|
uint64_t timeout = kTimeout100us;
|
|
|
|
|
if (active_wait) {
|
|
|
|
|
timeout = kUnlimitedWait;
|
2021-11-16 14:17:21 -05:00
|
|
|
}
|
|
|
|
|
if (active_wait_timeout) {
|
2023-08-07 13:46:02 -04:00
|
|
|
// If forced wait is set, then wait for 10us, else dont wait. (ns * K = us)
|
|
|
|
|
timeout = (forced_wait ? kForcedTimeout10us : ROC_ACTIVE_WAIT_TIMEOUT) * K;
|
2021-06-09 00:08:02 -07:00
|
|
|
if (timeout == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-07-19 15:05:24 -04:00
|
|
|
}
|
2021-02-17 14:48:08 -05:00
|
|
|
|
2021-07-19 15:05:24 -04:00
|
|
|
ClPrint(amd::LOG_INFO, amd::LOG_SIG, "Host active wait for Signal = (0x%lx) for %d ns",
|
|
|
|
|
signal.handle, timeout);
|
|
|
|
|
|
|
|
|
|
// Active wait with a timeout
|
|
|
|
|
if (hsa_signal_wait_scacquire(signal, HSA_SIGNAL_CONDITION_LT, kInitSignalValueOne,
|
|
|
|
|
timeout, HSA_WAIT_STATE_ACTIVE) != 0) {
|
|
|
|
|
if (active_wait_timeout) {
|
2021-02-17 14:48:08 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
2021-07-19 15:05:24 -04:00
|
|
|
ClPrint(amd::LOG_INFO, amd::LOG_SIG, "Host blocked wait for Signal = (0x%lx)",
|
2021-06-09 00:08:02 -07:00
|
|
|
signal.handle);
|
|
|
|
|
|
2021-07-19 15:05:24 -04:00
|
|
|
// Wait until the completion with CPU suspend
|
2021-06-09 00:08:02 -07:00
|
|
|
if (hsa_signal_wait_scacquire(signal, HSA_SIGNAL_CONDITION_LT, kInitSignalValueOne,
|
2021-07-19 15:05:24 -04:00
|
|
|
kUnlimitedWait, HSA_WAIT_STATE_BLOCKED) != 0) {
|
|
|
|
|
return false;
|
2021-06-09 00:08:02 -07:00
|
|
|
}
|
2021-02-17 14:48:08 -05:00
|
|
|
}
|
2020-09-25 12:56:48 -04:00
|
|
|
}
|
2021-06-09 00:08:02 -07:00
|
|
|
|
2020-09-25 12:56:48 -04:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-08 14:15:37 -08:00
|
|
|
inline void fetchSignalTime(hsa_signal_t signal, hsa_agent_t gpu_device,
|
|
|
|
|
uint64_t* start, uint64_t* end) {
|
|
|
|
|
if (start != nullptr && end != nullptr) {
|
|
|
|
|
hsa_amd_profiling_dispatch_time_t time = {};
|
|
|
|
|
hsa_amd_profiling_get_dispatch_time(gpu_device, signal, &time);
|
|
|
|
|
*start = time.start;
|
|
|
|
|
*end = time.end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-21 12:41:26 -04:00
|
|
|
// Timestamp for keeping track of some profiling information for various commands
|
|
|
|
|
// including EnqueueNDRangeKernel and clEnqueueCopyBuffer.
|
2021-07-30 18:07:34 -04:00
|
|
|
class Timestamp : public amd::ReferenceCountedObject {
|
2017-04-13 13:56:38 -04:00
|
|
|
private:
|
|
|
|
|
static double ticksToTime_;
|
2021-01-19 18:06:08 -05:00
|
|
|
|
|
|
|
|
uint64_t start_;
|
|
|
|
|
uint64_t end_;
|
2021-02-03 10:13:22 -05:00
|
|
|
VirtualGPU* gpu_; //!< Virtual GPU, associated with this timestamp
|
2021-07-16 18:20:51 -04:00
|
|
|
amd::Command& command_; ///!< Command, associated with this timestamp
|
2021-05-11 16:55:15 -07:00
|
|
|
amd::Command* parsedCommand_; //!< Command down the list, considering command_ as head
|
2021-05-27 16:48:03 -04:00
|
|
|
std::vector<ProfilingSignal*> signals_; //!< The list of all signals, associated with the TS
|
|
|
|
|
hsa_signal_t callback_signal_; //!< Signal associated with a callback for possible later update
|
2021-07-30 18:07:34 -04:00
|
|
|
amd::Monitor lock_; //!< Serialize timestamp update
|
2022-08-19 10:06:26 -04:00
|
|
|
bool accum_ena_ = false; //!< If TRUE then the accumulation of execution times has started
|
2023-04-18 17:46:55 +00:00
|
|
|
bool hasHwProfiling_ = false; //!< If TRUE then HwProfiling is enabled for the command
|
2021-05-27 16:48:03 -04:00
|
|
|
|
|
|
|
|
Timestamp(const Timestamp&) = delete;
|
|
|
|
|
Timestamp& operator=(const Timestamp&) = delete;
|
2017-04-13 13:56:38 -04:00
|
|
|
|
|
|
|
|
public:
|
2021-07-16 18:20:51 -04:00
|
|
|
Timestamp(VirtualGPU* gpu, amd::Command& command)
|
2021-02-03 10:13:22 -05:00
|
|
|
: start_(std::numeric_limits<uint64_t>::max())
|
|
|
|
|
, end_(0)
|
|
|
|
|
, gpu_(gpu)
|
2021-05-11 16:55:15 -07:00
|
|
|
, command_(command)
|
2021-05-27 16:48:03 -04:00
|
|
|
, parsedCommand_(nullptr)
|
2021-07-30 18:07:34 -04:00
|
|
|
, callback_signal_(hsa_signal_t{})
|
|
|
|
|
, lock_("Timestamp lock", true) {}
|
2021-02-03 10:13:22 -05:00
|
|
|
|
2021-02-26 16:17:30 -05:00
|
|
|
~Timestamp() {}
|
2021-02-03 10:13:22 -05:00
|
|
|
|
2022-03-25 17:37:11 +00:00
|
|
|
void getTime(uint64_t* start, uint64_t* end) {
|
2017-04-13 13:56:38 -04:00
|
|
|
checkGpuTime();
|
2022-03-08 14:15:37 -08:00
|
|
|
*start = start_;
|
|
|
|
|
*end = end_;
|
2017-04-13 13:56:38 -04:00
|
|
|
}
|
|
|
|
|
|
2023-04-18 17:46:55 +00:00
|
|
|
void AddProfilingSignal(ProfilingSignal* signal) {
|
|
|
|
|
signals_.push_back(signal);
|
|
|
|
|
hasHwProfiling_ = true;
|
|
|
|
|
}
|
2021-01-19 18:06:08 -05:00
|
|
|
|
2021-02-03 10:13:22 -05:00
|
|
|
const std::vector<ProfilingSignal*>& Signals() const { return signals_; }
|
2017-04-13 13:56:38 -04:00
|
|
|
|
2023-04-18 17:46:55 +00:00
|
|
|
const bool HwProfiling() const { return hasHwProfiling_; }
|
2017-04-13 13:56:38 -04:00
|
|
|
|
|
|
|
|
//! Finds execution ticks on GPU
|
2021-06-18 17:07:40 -04:00
|
|
|
void checkGpuTime();
|
2017-02-07 17:13:15 -05:00
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
// Start a timestamp (get timestamp from OS)
|
|
|
|
|
void start() { start_ = amd::Os::timeNanos(); }
|
2017-02-07 17:13:15 -05:00
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
// End a timestamp (get timestamp from OS)
|
2021-06-30 14:36:10 -04:00
|
|
|
void end() {
|
|
|
|
|
// Timestamp value can be updated by HW profiling if current command had a stall.
|
|
|
|
|
// Although CPU TS should be still valid in this situation, there are cases in VM mode
|
|
|
|
|
// when CPU timeline is out of sync with GPU timeline and shifted time can be reported
|
2021-07-06 14:09:22 -04:00
|
|
|
if (end_ == 0) {
|
2021-06-30 14:36:10 -04:00
|
|
|
end_ = amd::Os::timeNanos();
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-07 17:13:15 -05:00
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
static void setGpuTicksToTime(double ticksToTime) { ticksToTime_ = ticksToTime; }
|
|
|
|
|
static double getGpuTicksToTime() { return ticksToTime_; }
|
2021-02-03 10:13:22 -05:00
|
|
|
|
|
|
|
|
//! Returns amd::command assigned to this timestamp
|
2021-07-16 18:20:51 -04:00
|
|
|
amd::Command& command() const { return command_; }
|
2021-02-03 10:13:22 -05:00
|
|
|
|
2021-05-11 16:55:15 -07:00
|
|
|
//! Sets the parsed command
|
|
|
|
|
void setParsedCommand(amd::Command* command) { parsedCommand_ = command; }
|
|
|
|
|
|
|
|
|
|
//! Gets the parsed command
|
|
|
|
|
amd::Command* getParsedCommand() const { return parsedCommand_; }
|
|
|
|
|
|
2021-02-03 10:13:22 -05:00
|
|
|
//! Returns virtual GPU device, used with this timestamp
|
|
|
|
|
VirtualGPU* gpu() const { return gpu_; }
|
2021-05-27 16:48:03 -04:00
|
|
|
|
|
|
|
|
//! Updates the callback signal
|
|
|
|
|
void SetCallbackSignal(hsa_signal_t callback_signal) {
|
|
|
|
|
callback_signal_ = callback_signal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Returns the callback signal
|
|
|
|
|
hsa_signal_t GetCallbackSignal() const { return callback_signal_; }
|
2016-07-21 12:41:26 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class VirtualGPU : public device::VirtualDevice {
|
2017-04-13 13:56:38 -04:00
|
|
|
public:
|
|
|
|
|
class MemoryDependency : public amd::EmbeddedObject {
|
|
|
|
|
public:
|
|
|
|
|
//! Default constructor
|
|
|
|
|
MemoryDependency()
|
|
|
|
|
: memObjectsInQueue_(nullptr), numMemObjectsInQueue_(0), maxMemObjectsInQueue_(0) {}
|
|
|
|
|
|
|
|
|
|
~MemoryDependency() { delete[] memObjectsInQueue_; }
|
|
|
|
|
|
|
|
|
|
//! Creates memory dependecy structure
|
|
|
|
|
bool create(size_t numMemObj);
|
|
|
|
|
|
|
|
|
|
//! Notify the tracker about new kernel
|
|
|
|
|
void newKernel() { endMemObjectsInQueue_ = numMemObjectsInQueue_; }
|
|
|
|
|
|
|
|
|
|
//! Validates memory object on dependency
|
|
|
|
|
void validate(VirtualGPU& gpu, const Memory* memory, bool readOnly);
|
|
|
|
|
|
|
|
|
|
//! Clear memory dependency
|
|
|
|
|
void clear(bool all = true);
|
|
|
|
|
|
2019-09-17 19:47:11 -04:00
|
|
|
//! Max number of mem objects in the queue
|
|
|
|
|
size_t maxMemObjectsInQueue() const { return maxMemObjectsInQueue_; }
|
|
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
private:
|
|
|
|
|
struct MemoryState {
|
|
|
|
|
uint64_t start_; //! Busy memory start address
|
|
|
|
|
uint64_t end_; //! Busy memory end address
|
|
|
|
|
bool readOnly_; //! Current GPU state in the queue
|
2016-07-21 12:41:26 -04:00
|
|
|
};
|
|
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
MemoryState* memObjectsInQueue_; //!< Memory object state in the queue
|
|
|
|
|
size_t endMemObjectsInQueue_; //!< End of mem objects in the queue
|
|
|
|
|
size_t numMemObjectsInQueue_; //!< Number of mem objects in the queue
|
|
|
|
|
size_t maxMemObjectsInQueue_; //!< Maximum number of mem objects in the queue
|
|
|
|
|
};
|
|
|
|
|
|
2021-01-07 16:41:30 -05:00
|
|
|
class HwQueueTracker : public amd::EmbeddedObject {
|
|
|
|
|
public:
|
2023-11-21 03:41:49 +00:00
|
|
|
HwQueueTracker(const VirtualGPU& gpu): gpu_(gpu), handlerPending_(false) {}
|
2021-01-22 16:42:35 -05:00
|
|
|
|
|
|
|
|
~HwQueueTracker();
|
2021-01-07 16:41:30 -05:00
|
|
|
|
|
|
|
|
//! Creates a pool of signals for tracking of HW operations on the queue
|
2021-01-22 16:42:35 -05:00
|
|
|
bool Create();
|
2021-01-07 16:41:30 -05:00
|
|
|
|
|
|
|
|
//! Finds a free signal for the upcomming operation
|
|
|
|
|
hsa_signal_t ActiveSignal(hsa_signal_value_t init_val = kInitSignalValueOne,
|
2023-08-07 13:46:02 -04:00
|
|
|
Timestamp* ts = nullptr, bool forceHostWait = true);
|
2021-01-07 16:41:30 -05:00
|
|
|
|
|
|
|
|
//! Wait for the curent active signal. Can idle the queue
|
2021-04-30 15:05:54 -07:00
|
|
|
bool WaitCurrent() {
|
|
|
|
|
ProfilingSignal* signal = signal_list_[current_id_];
|
|
|
|
|
return CpuWaitForSignal(signal);
|
|
|
|
|
}
|
2021-01-22 16:42:35 -05:00
|
|
|
|
|
|
|
|
//! Update current active engine
|
|
|
|
|
void SetActiveEngine(HwQueueEngine engine = HwQueueEngine::Compute) { engine_ = engine; }
|
2021-07-14 19:56:39 -04:00
|
|
|
HwQueueEngine GetActiveEngine() const { return engine_; }
|
2021-01-07 16:41:30 -05:00
|
|
|
|
|
|
|
|
//! Returns the last submitted signal for a wait
|
2021-05-21 18:06:40 -04:00
|
|
|
std::vector<hsa_signal_t>& WaitingSignal(HwQueueEngine engine = HwQueueEngine::Compute);
|
2021-01-07 16:41:30 -05:00
|
|
|
|
2021-01-21 17:29:34 -05:00
|
|
|
//! Resets current signal back to the previous one. It's necessary in a case of ROCr failure.
|
|
|
|
|
void ResetCurrentSignal();
|
|
|
|
|
|
2021-05-21 18:06:40 -04:00
|
|
|
//! Adds an external signal(submission in another queue) for dependency tracking
|
|
|
|
|
void AddExternalSignal(ProfilingSignal* signal) {
|
|
|
|
|
external_signals_.push_back(signal);
|
2021-01-22 16:42:35 -05:00
|
|
|
engine_ = HwQueueEngine::External;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 18:06:40 -04:00
|
|
|
//! Get the last active signal on the queue
|
2021-01-22 16:42:35 -05:00
|
|
|
ProfilingSignal* GetLastSignal() const { return signal_list_[current_id_]; }
|
|
|
|
|
|
2021-12-13 19:38:29 -08:00
|
|
|
//! Clear external signals
|
|
|
|
|
void ClearExternalSignals() { external_signals_.clear(); }
|
|
|
|
|
|
|
|
|
|
//! Empty check for external signals
|
|
|
|
|
bool IsExternalSignalListEmpty() const { return external_signals_.empty(); }
|
|
|
|
|
|
2023-11-21 03:41:49 +00:00
|
|
|
//! Set the status to indicate a pending handler
|
|
|
|
|
void SetHandlerPending(bool pending) { handlerPending_ = pending; }
|
|
|
|
|
|
|
|
|
|
//! Check if callback has been queued
|
|
|
|
|
bool IsHandlerPending() const { return handlerPending_; }
|
|
|
|
|
|
2023-06-22 11:05:11 -07:00
|
|
|
//! Get/Set SDMA profiling
|
|
|
|
|
bool GetSDMAProfiling() { return sdma_profiling_; }
|
|
|
|
|
void SetSDMAProfiling(bool profile) {
|
|
|
|
|
sdma_profiling_ = profile;
|
|
|
|
|
hsa_amd_profiling_async_copy_enable(profile);
|
|
|
|
|
}
|
2021-01-22 16:42:35 -05:00
|
|
|
private:
|
2021-01-07 16:41:30 -05:00
|
|
|
//! Wait for the next active signal
|
|
|
|
|
void WaitNext() {
|
|
|
|
|
size_t next = (current_id_ + 1) % signal_list_.size();
|
2021-04-30 15:05:54 -07:00
|
|
|
ProfilingSignal* signal = signal_list_[next];
|
|
|
|
|
CpuWaitForSignal(signal);
|
2021-01-07 16:41:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Wait for the provided signal
|
2021-01-22 16:42:35 -05:00
|
|
|
bool CpuWaitForSignal(ProfilingSignal* signal);
|
|
|
|
|
|
|
|
|
|
HwQueueEngine engine_ = HwQueueEngine::Unknown; //!< Engine used in the current operations
|
|
|
|
|
std::vector<ProfilingSignal*> signal_list_; //!< The pool of all signals for processing
|
|
|
|
|
size_t current_id_ = 0; //!< Last submitted signal
|
|
|
|
|
bool sdma_profiling_ = false; //!< If TRUE, then SDMA profiling is enabled
|
|
|
|
|
const VirtualGPU& gpu_; //!< VirtualGPU, associated with this tracker
|
2023-02-28 09:41:17 -08:00
|
|
|
std::vector<ProfilingSignal*> external_signals_; //!< External signals for a wait in this queue
|
2021-05-21 18:06:40 -04:00
|
|
|
std::vector<hsa_signal_t> waiting_signals_; //!< Current waiting signals in this queue
|
2023-11-21 03:41:49 +00:00
|
|
|
bool handlerPending_; //!< This indicates if we have queued a callback handler
|
2021-01-07 16:41:30 -05:00
|
|
|
};
|
|
|
|
|
|
2020-05-12 10:31:07 -04:00
|
|
|
VirtualGPU(Device& device, bool profiling = false, bool cooperative = false,
|
2020-06-04 01:16:31 -04:00
|
|
|
const std::vector<uint32_t>& cuMask = {},
|
|
|
|
|
amd::CommandQueue::Priority priority = amd::CommandQueue::Priority::Normal);
|
2017-04-13 13:56:38 -04:00
|
|
|
~VirtualGPU();
|
|
|
|
|
|
2020-03-27 15:43:06 -04:00
|
|
|
bool create();
|
2017-04-13 13:56:38 -04:00
|
|
|
const Device& dev() const { return roc_device_; }
|
|
|
|
|
|
2024-03-21 18:26:01 +00:00
|
|
|
void profilingBegin(amd::Command& command, bool sdmaProfiling = false);
|
|
|
|
|
void profilingEnd(amd::Command& command);
|
2017-04-13 13:56:38 -04:00
|
|
|
|
2021-02-26 16:17:30 -05:00
|
|
|
void updateCommandsState(amd::Command* list) const;
|
2017-04-13 13:56:38 -04:00
|
|
|
|
|
|
|
|
void submitReadMemory(amd::ReadMemoryCommand& cmd);
|
|
|
|
|
void submitWriteMemory(amd::WriteMemoryCommand& cmd);
|
|
|
|
|
void submitCopyMemory(amd::CopyMemoryCommand& cmd);
|
2017-06-12 13:31:09 -04:00
|
|
|
void submitCopyMemoryP2P(amd::CopyMemoryP2PCommand& cmd);
|
2017-04-13 13:56:38 -04:00
|
|
|
void submitMapMemory(amd::MapMemoryCommand& cmd);
|
|
|
|
|
void submitUnmapMemory(amd::UnmapMemoryCommand& cmd);
|
|
|
|
|
void submitKernel(amd::NDRangeKernelCommand& cmd);
|
|
|
|
|
bool submitKernelInternal(const amd::NDRangeContainer& sizes, //!< Workload sizes
|
|
|
|
|
const amd::Kernel& kernel, //!< Kernel for execution
|
|
|
|
|
const_address parameters, //!< Parameters for the kernel
|
2019-02-21 17:42:08 -05:00
|
|
|
void* event_handle, //!< Handle to OCL event for debugging
|
2019-06-12 10:00:38 -04:00
|
|
|
uint32_t sharedMemBytes = 0, //!< Shared memory size
|
2023-01-23 17:40:30 -05:00
|
|
|
amd::NDRangeKernelCommand* vcmd = nullptr, //!< Original launch command
|
|
|
|
|
hsa_kernel_dispatch_packet_t* aql_packet = nullptr //!< Scheduler launch
|
2017-04-13 13:56:38 -04:00
|
|
|
);
|
|
|
|
|
void submitNativeFn(amd::NativeFnCommand& cmd);
|
|
|
|
|
void submitMarker(amd::Marker& cmd);
|
2023-10-26 20:06:18 +00:00
|
|
|
void submitAccumulate(amd::AccumulateCommand& cmd);
|
2017-04-13 13:56:38 -04:00
|
|
|
void submitAcquireExtObjects(amd::AcquireExtObjectsCommand& cmd);
|
|
|
|
|
void submitReleaseExtObjects(amd::ReleaseExtObjectsCommand& cmd);
|
2017-10-11 15:44:54 -04:00
|
|
|
void submitPerfCounter(amd::PerfCounterCommand& cmd);
|
2017-04-13 13:56:38 -04:00
|
|
|
|
|
|
|
|
void flush(amd::Command* list = nullptr, bool wait = false);
|
|
|
|
|
void submitFillMemory(amd::FillMemoryCommand& cmd);
|
2021-02-08 21:51:18 -08:00
|
|
|
void submitStreamOperation(amd::StreamOperationCommand& cmd);
|
2023-07-21 18:46:33 -04:00
|
|
|
void submitVirtualMap(amd::VirtualMapCommand& cmd);
|
2017-04-13 13:56:38 -04:00
|
|
|
void submitMigrateMemObjects(amd::MigrateMemObjectsCommand& cmd);
|
|
|
|
|
|
2018-08-08 18:58:03 -04:00
|
|
|
void submitSvmFreeMemory(amd::SvmFreeMemoryCommand& cmd);
|
|
|
|
|
void submitSvmCopyMemory(amd::SvmCopyMemoryCommand& cmd);
|
|
|
|
|
void submitSvmFillMemory(amd::SvmFillMemoryCommand& cmd);
|
2018-08-16 13:59:59 -04:00
|
|
|
void submitSvmMapMemory(amd::SvmMapMemoryCommand& cmd);
|
|
|
|
|
void submitSvmUnmapMemory(amd::SvmUnmapMemoryCommand& cmd);
|
2020-06-11 14:26:15 -04:00
|
|
|
void submitSvmPrefetchAsync(amd::SvmPrefetchAsyncCommand& cmd);
|
2018-08-08 18:58:03 -04:00
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
// { roc OpenCL integration
|
|
|
|
|
// Added these stub (no-ops) implementation of pure virtual methods,
|
|
|
|
|
// when integrating HSA and OpenCL branches.
|
|
|
|
|
// TODO: After inegration, whoever is working on VirtualGPU should write
|
2017-06-12 13:31:09 -04:00
|
|
|
// actual implementation.
|
2017-04-13 13:56:38 -04:00
|
|
|
virtual void submitSignal(amd::SignalCommand& cmd) {}
|
|
|
|
|
virtual void submitMakeBuffersResident(amd::MakeBuffersResidentCommand& cmd) {}
|
|
|
|
|
|
|
|
|
|
void submitThreadTraceMemObjects(amd::ThreadTraceMemObjectsCommand& cmd) {}
|
|
|
|
|
void submitThreadTrace(amd::ThreadTraceCommand& vcmd) {}
|
|
|
|
|
|
2021-04-22 19:24:30 -04:00
|
|
|
virtual void submitExternalSemaphoreCmd(amd::ExternalSemaphoreCmd& cmd){}
|
2021-10-27 16:22:40 -04:00
|
|
|
|
|
|
|
|
virtual address allocKernelArguments(size_t size, size_t alignment) final;
|
|
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
/**
|
|
|
|
|
* @brief Waits on an outstanding kernel without regard to how
|
|
|
|
|
* it was dispatched - with or without a signal
|
|
|
|
|
*
|
2020-09-25 12:56:48 -04:00
|
|
|
* @return bool true if Wait returned successfully, false otherwise
|
2017-04-13 13:56:38 -04:00
|
|
|
*/
|
2021-04-05 15:23:07 -07:00
|
|
|
bool releaseGpuMemoryFence(bool skip_copy_wait = false);
|
2017-04-13 13:56:38 -04:00
|
|
|
|
2021-01-22 16:42:35 -05:00
|
|
|
hsa_agent_t gpu_device() const { return gpu_device_; }
|
2017-04-13 13:56:38 -04:00
|
|
|
hsa_queue_t* gpu_queue() { return gpu_queue_; }
|
|
|
|
|
|
|
|
|
|
// Return pointer to PrintfDbg
|
|
|
|
|
PrintfDbg* printfDbg() const { return printfdbg_; }
|
|
|
|
|
|
|
|
|
|
//! Returns memory dependency class
|
|
|
|
|
MemoryDependency& memoryDependency() { return memoryDependency_; }
|
|
|
|
|
|
|
|
|
|
//! Detects memory dependency for HSAIL kernels and uses appropriate AQL header
|
|
|
|
|
bool processMemObjects(const amd::Kernel& kernel, //!< AMD kernel object for execution
|
2018-08-03 16:05:12 -04:00
|
|
|
const_address params, //!< Pointer to the param's store
|
2019-06-12 10:00:38 -04:00
|
|
|
size_t& ldsAddress, //!< LDS usage
|
2021-03-26 03:31:59 -04:00
|
|
|
bool cooperativeGroups, //!< Dispatch with cooperative groups
|
|
|
|
|
bool& imageBufferWrtBack, //!< Image buffer write back is required
|
2023-02-28 09:41:17 -08:00
|
|
|
std::vector<device::Memory*>& wrtBackImageBuffer //!< Images for writeback
|
2017-04-13 13:56:38 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//! Adds a stage write buffer into a list
|
|
|
|
|
void addXferWrite(Memory& memory);
|
|
|
|
|
|
|
|
|
|
//! Releases stage write buffers
|
|
|
|
|
void releaseXferWrite();
|
|
|
|
|
|
|
|
|
|
//! Adds a pinned memory object into a map
|
|
|
|
|
void addPinnedMem(amd::Memory* mem);
|
|
|
|
|
|
|
|
|
|
//! Release pinned memory objects
|
|
|
|
|
void releasePinnedMem();
|
|
|
|
|
|
|
|
|
|
//! Finds if pinned memory is cached
|
|
|
|
|
amd::Memory* findPinnedMem(void* addr, size_t size);
|
|
|
|
|
|
|
|
|
|
void enableSyncBlit() const;
|
|
|
|
|
|
2020-05-14 13:03:36 -07:00
|
|
|
void hasPendingDispatch() { hasPendingDispatch_ = true; }
|
2022-02-15 12:55:04 +00:00
|
|
|
bool IsPendingDispatch() const { return (hasPendingDispatch_) ? true : false; }
|
2020-05-14 13:03:36 -07:00
|
|
|
void addSystemScope() { addSystemScope_ = true; }
|
2020-10-16 14:20:58 -04:00
|
|
|
void SetCopyCommandType(cl_command_type type) { copy_command_type_ = type; }
|
2019-06-12 10:00:38 -04:00
|
|
|
|
2021-01-07 16:41:30 -05:00
|
|
|
HwQueueTracker& Barriers() { return barriers_; }
|
|
|
|
|
|
|
|
|
|
Timestamp* timestamp() const { return timestamp_; }
|
|
|
|
|
|
2023-11-21 03:41:49 +00:00
|
|
|
//! Indicates the status of the callback handler. The callback would process the commands
|
|
|
|
|
//! and would collect profiling data, update refcounts
|
|
|
|
|
bool isHandlerPending() const { return barriers_.IsHandlerPending(); }
|
|
|
|
|
|
2022-07-11 16:16:07 -07:00
|
|
|
void* allocKernArg(size_t size, size_t alignment);
|
2022-10-03 09:08:40 -07:00
|
|
|
bool isFenceDirty() const { return fence_dirty_; }
|
2023-10-09 23:35:11 +00:00
|
|
|
void setLastUsedSdmaEngine(uint32_t mask) { lastUsedSdmaEngineMask_ = mask; }
|
|
|
|
|
uint32_t getLastUsedSdmaEngine() const { return lastUsedSdmaEngineMask_.load(); }
|
2017-04-13 13:56:38 -04:00
|
|
|
// } roc OpenCL integration
|
|
|
|
|
private:
|
2021-05-21 18:06:40 -04:00
|
|
|
//! Dispatches a barrier with blocking HSA signals
|
|
|
|
|
void dispatchBlockingWait();
|
|
|
|
|
|
2023-10-26 20:06:18 +00:00
|
|
|
inline bool dispatchAqlPacket(uint8_t* aqlpacket, amd::AccumulateCommand* vcmd = nullptr);
|
2023-07-19 10:10:37 +00:00
|
|
|
bool dispatchAqlPacket(hsa_kernel_dispatch_packet_t* packet, uint16_t header, uint16_t rest,
|
|
|
|
|
bool blocking = true, bool capturing = false,
|
|
|
|
|
const uint8_t* aqlPacket = nullptr);
|
2020-10-17 10:04:58 -07:00
|
|
|
bool dispatchAqlPacket(hsa_barrier_and_packet_t* packet, uint16_t header,
|
|
|
|
|
uint16_t rest, bool blocking = true);
|
|
|
|
|
template <typename AqlPacket> bool dispatchGenericAqlPacket(AqlPacket* packet, uint16_t header,
|
2024-03-25 23:39:46 +00:00
|
|
|
uint16_t rest, bool blocking);
|
2023-06-17 13:48:05 +00:00
|
|
|
|
2021-10-25 15:06:31 -04:00
|
|
|
void dispatchBarrierPacket(uint16_t packetHeader, bool skipSignal = false,
|
|
|
|
|
hsa_signal_t signal = hsa_signal_t{0});
|
2020-10-17 10:04:58 -07:00
|
|
|
bool dispatchCounterAqlPacket(hsa_ext_amd_aql_pm4_packet_t* packet, const uint32_t gfxVersion,
|
|
|
|
|
bool blocking, const hsa_ven_amd_aqlprofile_1_00_pfn_t* extApi);
|
2022-11-30 18:35:33 -08:00
|
|
|
void dispatchBarrierValuePacket(uint16_t packetHeader,
|
2023-01-10 13:10:19 -08:00
|
|
|
bool resolveDepSignal = false,
|
2022-11-30 18:35:33 -08:00
|
|
|
hsa_signal_t signal = hsa_signal_t{0},
|
|
|
|
|
hsa_signal_value_t value = 0,
|
|
|
|
|
hsa_signal_value_t mask = 0,
|
|
|
|
|
hsa_signal_condition32_t cond = HSA_SIGNAL_CONDITION_EQ,
|
|
|
|
|
bool skipTs = false,
|
|
|
|
|
hsa_signal_t completionSignal = hsa_signal_t{0});
|
2020-10-17 10:04:58 -07:00
|
|
|
void initializeDispatchPacket(hsa_kernel_dispatch_packet_t* packet,
|
|
|
|
|
amd::NDRangeContainer& sizes);
|
2017-04-13 13:56:38 -04:00
|
|
|
|
2021-01-07 16:41:30 -05:00
|
|
|
bool initPool(size_t kernarg_pool_size);
|
2017-04-13 13:56:38 -04:00
|
|
|
void destroyPool();
|
|
|
|
|
|
2021-10-27 17:13:52 -04:00
|
|
|
void resetKernArgPool() {
|
|
|
|
|
kernarg_pool_cur_offset_ = 0;
|
|
|
|
|
kernarg_pool_chunk_end_ = kernarg_pool_size_ / KernelArgPoolNumSignal;
|
|
|
|
|
active_chunk_ = 0;
|
|
|
|
|
}
|
2017-04-13 13:56:38 -04:00
|
|
|
|
2018-06-12 16:17:29 -04:00
|
|
|
uint64_t getVQVirtualAddress();
|
|
|
|
|
|
|
|
|
|
bool createSchedulerParam();
|
|
|
|
|
|
|
|
|
|
//! Returns TRUE if virtual queue was successfully allocatted
|
|
|
|
|
bool createVirtualQueue(uint deviceQueueSize);
|
|
|
|
|
|
2018-08-08 18:58:03 -04:00
|
|
|
//! Common function for fill memory used by both svm Fill and non-svm fill
|
|
|
|
|
bool fillMemory(cl_command_type type, //!< the command type
|
|
|
|
|
amd::Memory* amdMemory, //!< memory object to fill
|
|
|
|
|
const void* pattern, //!< pattern to fill the memory
|
|
|
|
|
size_t patternSize, //!< pattern size
|
2021-10-19 13:00:51 -04:00
|
|
|
const amd::Coord3D& surface, //!< Whole Surface of mem object.
|
2018-08-08 18:58:03 -04:00
|
|
|
const amd::Coord3D& origin, //!< memory origin
|
2021-08-24 11:25:28 -07:00
|
|
|
const amd::Coord3D& size, //!< memory size for filling
|
|
|
|
|
bool forceBlit = false //!< force shader blit path
|
2018-08-08 18:58:03 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//! Common function for memory copy used by both svm Copy and non-svm Copy
|
|
|
|
|
bool copyMemory(cl_command_type type, //!< the command type
|
|
|
|
|
amd::Memory& srcMem, //!< source memory object
|
|
|
|
|
amd::Memory& dstMem, //!< destination memory object
|
|
|
|
|
bool entire, //!< flag of entire memory copy
|
|
|
|
|
const amd::Coord3D& srcOrigin, //!< source memory origin
|
|
|
|
|
const amd::Coord3D& dstOrigin, //!< destination memory object
|
|
|
|
|
const amd::Coord3D& size, //!< copy size
|
|
|
|
|
const amd::BufferRect& srcRect, //!< region of source for copy
|
2022-12-01 15:55:39 +00:00
|
|
|
const amd::BufferRect& dstRect, //!< region of destination for copy
|
|
|
|
|
amd::CopyMetadata copyMetadata =
|
|
|
|
|
amd::CopyMetadata() //!< Memory copy MetaData
|
2018-08-08 18:58:03 -04:00
|
|
|
);
|
|
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
//! Updates AQL header for the upcomming dispatch
|
|
|
|
|
void setAqlHeader(uint16_t header) { aqlHeader_ = header; }
|
|
|
|
|
|
2020-09-25 12:56:48 -04:00
|
|
|
//! Resets the current queue state. Note: should be called after AQL queue becomes idle
|
|
|
|
|
void ResetQueueStates();
|
|
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
std::vector<Memory*> xferWriteBuffers_; //!< Stage write buffers
|
|
|
|
|
std::vector<amd::Memory*> pinnedMems_; //!< Pinned memory list
|
|
|
|
|
|
2020-03-27 15:43:06 -04:00
|
|
|
//! Queue state flags
|
|
|
|
|
union {
|
|
|
|
|
struct {
|
2021-12-17 12:41:33 -08:00
|
|
|
uint32_t hasPendingDispatch_ : 1; //!< A kernel dispatch is outstanding
|
|
|
|
|
uint32_t profiling_ : 1; //!< Profiling is enabled
|
|
|
|
|
uint32_t cooperative_ : 1; //!< Cooperative launch is enabled
|
|
|
|
|
uint32_t addSystemScope_ : 1; //!< Insert a system scope to the next aql
|
|
|
|
|
uint32_t tracking_created_ : 1; //!< Enabled if tracking object was properly initialized
|
|
|
|
|
uint32_t retainExternalSignals_ : 1; //!< Indicate to retain external signal array
|
2020-03-27 15:43:06 -04:00
|
|
|
};
|
|
|
|
|
uint32_t state_;
|
|
|
|
|
};
|
2020-01-17 15:51:03 -05:00
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
Timestamp* timestamp_;
|
|
|
|
|
hsa_agent_t gpu_device_; //!< Physical device
|
|
|
|
|
hsa_queue_t* gpu_queue_; //!< Queue associated with a gpu
|
|
|
|
|
hsa_barrier_and_packet_t barrier_packet_;
|
2023-04-26 15:47:26 -07:00
|
|
|
hsa_amd_barrier_value_packet_t barrier_value_packet_;
|
2021-01-07 16:41:30 -05:00
|
|
|
|
2017-04-13 13:56:38 -04:00
|
|
|
uint32_t dispatch_id_; //!< This variable must be updated atomically.
|
|
|
|
|
Device& roc_device_; //!< roc device object
|
|
|
|
|
PrintfDbg* printfdbg_;
|
|
|
|
|
MemoryDependency memoryDependency_; //!< Memory dependency class
|
|
|
|
|
uint16_t aqlHeader_; //!< AQL header for dispatch
|
|
|
|
|
|
2018-06-12 16:17:29 -04:00
|
|
|
amd::Memory* virtualQueue_; //!< Virtual device queue
|
|
|
|
|
uint deviceQueueSize_; //!< Device queue size
|
2023-02-28 09:41:17 -08:00
|
|
|
uint maskGroups_; //!< The number of mask groups processed in the scheduler by
|
|
|
|
|
//!< one thread
|
2018-06-12 16:17:29 -04:00
|
|
|
uint schedulerThreads_; //!< The number of scheduler threads
|
|
|
|
|
|
|
|
|
|
amd::Memory* schedulerParam_;
|
|
|
|
|
hsa_queue_t* schedulerQueue_;
|
|
|
|
|
hsa_signal_t schedulerSignal_;
|
|
|
|
|
|
2021-01-07 16:41:30 -05:00
|
|
|
HwQueueTracker barriers_; //!< Tracks active barriers in ROCr
|
|
|
|
|
|
2021-10-25 15:06:31 -04:00
|
|
|
//!< The number of chunks the kernel arg pool will be divided
|
2022-07-12 11:39:54 -07:00
|
|
|
static constexpr uint32_t KernelArgPoolNumSignal = 4;
|
2021-10-25 15:06:31 -04:00
|
|
|
address kernarg_pool_base_;
|
|
|
|
|
uint32_t kernarg_pool_size_;
|
|
|
|
|
uint32_t kernarg_pool_chunk_end_; //!< The end offset of the current chunck
|
|
|
|
|
uint32_t active_chunk_; //!< The index of the current active chunk
|
|
|
|
|
uint32_t kernarg_pool_cur_offset_;
|
2023-02-28 09:41:17 -08:00
|
|
|
std::vector<hsa_signal_t> kernarg_pool_signal_; //!< Pool of HSA signals to manage
|
|
|
|
|
//!< multiple chunks
|
2017-04-13 13:56:38 -04:00
|
|
|
|
|
|
|
|
friend class Timestamp;
|
2017-10-11 15:44:54 -04:00
|
|
|
|
|
|
|
|
// PM4 packet for gfx8 performance counter
|
|
|
|
|
enum {
|
|
|
|
|
SLOT_PM4_SIZE_DW = HSA_VEN_AMD_AQLPROFILE_LEGACY_PM4_PACKET_SIZE/ sizeof(uint32_t),
|
|
|
|
|
SLOT_PM4_SIZE_AQLP = HSA_VEN_AMD_AQLPROFILE_LEGACY_PM4_PACKET_SIZE/ 64
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-09 12:24:11 -04:00
|
|
|
uint16_t dispatchPacketHeaderNoSync_;
|
|
|
|
|
uint16_t dispatchPacketHeader_;
|
2020-05-12 10:31:07 -04:00
|
|
|
|
2020-06-04 01:16:31 -04:00
|
|
|
//!< bit-vector representing the CU mask. Each active bit represents using one CU
|
2020-08-01 12:55:11 -04:00
|
|
|
const std::vector<uint32_t> cuMask_;
|
2020-06-04 01:16:31 -04:00
|
|
|
amd::CommandQueue::Priority priority_; //!< The priority for the hsa queue
|
2020-10-16 14:20:58 -04:00
|
|
|
|
|
|
|
|
cl_command_type copy_command_type_; //!< Type of the copy command, used for ROC profiler
|
|
|
|
|
//!< OCL doesn't distinguish diffrent copy types,
|
|
|
|
|
//!< but ROC profiler expects D2H or H2D detection
|
2022-09-20 21:56:02 -07:00
|
|
|
int fence_state_; //!< Fence scope
|
|
|
|
|
//!< kUnknown/kFlushedToDevice/kFlushedToSystem
|
2022-10-03 09:08:40 -07:00
|
|
|
bool fence_dirty_; //!< Fence modified flag
|
2023-10-09 23:35:11 +00:00
|
|
|
|
|
|
|
|
std::atomic<uint> lastUsedSdmaEngineMask_; //!< Last Used SDMA Engine mask
|
2024-03-15 19:59:29 +00:00
|
|
|
|
|
|
|
|
using KernelArgImpl = device::Settings::KernelArgImpl;
|
2016-07-21 12:41:26 -04:00
|
|
|
};
|
|
|
|
|
}
|