SWDEV-77148 - Add UberTrace support to PAL device
This PR adds UberTrace-based tracing support to ROCclr's PAL device class. Legacy RGP-based tracing is still available and is the default. If UberTrace support is enabled tool-side, this new code path will activate. Change-Id: I268b2dcef70e850a50e2caef8355f38bf51d4641
This commit is contained in:
@@ -76,6 +76,7 @@ target_sources(rocclr PRIVATE
|
||||
${ROCCLR_SRC_DIR}/device/pal/palsignal.cpp
|
||||
${ROCCLR_SRC_DIR}/device/pal/palthreadtrace.cpp
|
||||
${ROCCLR_SRC_DIR}/device/pal/paltimestamp.cpp
|
||||
${ROCCLR_SRC_DIR}/device/pal/palubercapturemgr.cpp
|
||||
${ROCCLR_SRC_DIR}/device/pal/palvirtual.cpp)
|
||||
|
||||
target_compile_definitions(rocclr PUBLIC WITH_PAL_DEVICE PAL_GPUOPEN_OCL)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "device/pal/paldefs.hpp"
|
||||
#include "palDeveloperHooks.h"
|
||||
|
||||
namespace amd::pal {
|
||||
|
||||
class Device;
|
||||
class VirtualGPU;
|
||||
class HSAILKernel;
|
||||
|
||||
// ================================================================================================
|
||||
class ICaptureMgr {
|
||||
public:
|
||||
virtual bool Update(Pal::IPlatform* platform) = 0;
|
||||
|
||||
virtual void PreDispatch(VirtualGPU* gpu,
|
||||
const HSAILKernel& kernel,
|
||||
size_t x, size_t y, size_t z) = 0;
|
||||
virtual void PostDispatch(VirtualGPU* gpu) = 0;
|
||||
|
||||
virtual void FinishRGPTrace(VirtualGPU* gpu, bool aborted) = 0;
|
||||
|
||||
virtual void WriteBarrierStartMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const = 0;
|
||||
virtual void WriteBarrierEndMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const = 0;
|
||||
|
||||
virtual bool RegisterTimedQueue(uint32_t queue_id,
|
||||
Pal::IQueue* iQueue, bool* debug_vmid) const = 0;
|
||||
|
||||
virtual Pal::Result TimedQueueSubmit(Pal::IQueue* queue, uint64_t cmdId,
|
||||
const Pal::SubmitInfo& submitInfo) const = 0;
|
||||
|
||||
virtual uint64_t AddElfBinary(const void* exe_binary, size_t exe_binary_size,
|
||||
const void* elf_binary, size_t elf_binary_size,
|
||||
Pal::IGpuMemory* pGpuMemory, size_t offset) = 0;
|
||||
};
|
||||
|
||||
} // namespace amd::pal
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "device/pal/paldefs.hpp"
|
||||
#include "device/pal/palmemory.hpp"
|
||||
#include "device/pal/paldevice.hpp"
|
||||
#include "device/pal/palgpuopen.hpp"
|
||||
#include "device/pal/palubercapturemgr.hpp"
|
||||
#include "utils/flags.hpp"
|
||||
#include "utils/versions.hpp"
|
||||
#include "thread/monitor.hpp"
|
||||
@@ -59,6 +61,7 @@
|
||||
#ifdef PAL_GPUOPEN_OCL
|
||||
// gpuutil headers
|
||||
#include "gpuUtil/palGpaSession.h"
|
||||
#include "palTraceSession.h"
|
||||
#include "devDriverServer.h"
|
||||
#include "protocols/rgpServer.h"
|
||||
#include "protocols/driverControlServer.h"
|
||||
@@ -816,7 +819,7 @@ Device::Device()
|
||||
globalScratchBuf_(nullptr),
|
||||
srdManager_(nullptr),
|
||||
resourceList_(nullptr),
|
||||
rgpCaptureMgr_(nullptr) {}
|
||||
captureMgr_(nullptr) {}
|
||||
|
||||
Device::~Device() {
|
||||
if (p2p_stage_ != nullptr) {
|
||||
@@ -877,7 +880,7 @@ Device::~Device() {
|
||||
device_ = nullptr;
|
||||
|
||||
// Delete developer driver manager
|
||||
delete rgpCaptureMgr_;
|
||||
delete captureMgr_;
|
||||
}
|
||||
|
||||
extern const char* SchedulerSourceCode;
|
||||
@@ -969,10 +972,21 @@ bool Device::create(Pal::IDevice* device) {
|
||||
// Make sure CP DMA can be used for all possible transfers
|
||||
palSettings->cpDmaCmdCopyMemoryMaxBytes = 0xFFFFFFFF;
|
||||
|
||||
// Create RGP capture manager
|
||||
// Create RGP / UberTrace capture manager
|
||||
// Note: RGP initialization in PAL must be performed before CommitSettingsAndInit()
|
||||
rgpCaptureMgr_ = RgpCaptureMgr::Create(platform_, *this);
|
||||
if (nullptr != rgpCaptureMgr_) {
|
||||
#if PAL_BUILD_RDF
|
||||
if ((platform_->GetTraceSession() != nullptr) &&
|
||||
(platform_->GetTraceSession()->IsTracingEnabled()))
|
||||
{
|
||||
captureMgr_ = UberTraceCaptureMgr::Create(platform_, *this);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
captureMgr_ = RgpCaptureMgr::Create(platform_, *this);
|
||||
}
|
||||
|
||||
if (nullptr != captureMgr_) {
|
||||
// KMD forced DWORD alignment for debug VMID, request it back to Unaligned
|
||||
palSettings->hardwareBufferAlignmentMode = Pal::BufferAlignmentMode::Unaligned;
|
||||
Pal::IPlatform::InstallDeveloperCb(iPlat(), &Device::PalDeveloperCallback, this);
|
||||
@@ -1113,10 +1127,10 @@ void PAL_STDCALL Device::PalDeveloperCallback(void* pPrivateData, const Pal::uin
|
||||
|
||||
switch (type) {
|
||||
case Pal::Developer::CallbackType::BarrierBegin:
|
||||
device->rgpCaptureMgr()->WriteBarrierStartMarker(gpu, barrier);
|
||||
device->captureMgr()->WriteBarrierStartMarker(gpu, barrier);
|
||||
break;
|
||||
case Pal::Developer::CallbackType::BarrierEnd:
|
||||
device->rgpCaptureMgr()->WriteBarrierEndMarker(gpu, barrier);
|
||||
device->captureMgr()->WriteBarrierEndMarker(gpu, barrier);
|
||||
break;
|
||||
case Pal::Developer::CallbackType::ImageBarrier:
|
||||
assert(false);
|
||||
@@ -1186,10 +1200,10 @@ bool Device::initializeHeapResources() {
|
||||
}
|
||||
|
||||
// Update RGP capture manager
|
||||
if (rgpCaptureMgr_ != nullptr) {
|
||||
if (!rgpCaptureMgr_->Update(platform_)) {
|
||||
delete rgpCaptureMgr_;
|
||||
rgpCaptureMgr_ = nullptr;
|
||||
if (captureMgr_ != nullptr) {
|
||||
if (!captureMgr_->Update(platform_)) {
|
||||
delete captureMgr_;
|
||||
captureMgr_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "device/pal/paldefs.hpp"
|
||||
#include "device/pal/palsettings.hpp"
|
||||
#include "device/pal/palappprofile.hpp"
|
||||
#include "device/pal/palgpuopen.hpp"
|
||||
#include "device/pal/palcapturemgr.hpp"
|
||||
#include "device/pal/palsignal.hpp"
|
||||
#include "acl.h"
|
||||
#include "memory"
|
||||
@@ -587,7 +587,8 @@ class Device : public NullDevice {
|
||||
//! Allow access for peer device
|
||||
bool deviceAllowAccess(void* dst) const;
|
||||
|
||||
RgpCaptureMgr* rgpCaptureMgr() const { return rgpCaptureMgr_; }
|
||||
//! Returns a handle to the capture manager (RGP or UberTrace)
|
||||
ICaptureMgr* captureMgr() const { return captureMgr_; }
|
||||
|
||||
//! Update free memory for OCL extension
|
||||
void updateAllocedMemory(Pal::GpuHeap heap, //!< PAL GPU heap for update
|
||||
@@ -750,7 +751,7 @@ class Device : public NullDevice {
|
||||
mutable std::atomic<Pal::gpusize>
|
||||
allocedMem[Pal::GpuHeap::GpuHeapCount]; //!< Free memory counter
|
||||
std::unordered_set<Resource*>* resourceList_; //!< Active resource list
|
||||
RgpCaptureMgr* rgpCaptureMgr_; //!< RGP capture manager
|
||||
ICaptureMgr* captureMgr_; //!< RGP/UberTrace capture manager
|
||||
Pal::GpuMemoryHeapProperties
|
||||
heaps_[Pal::GpuHeapCount]; //!< Information about heaps, returned from PAL
|
||||
std::map<Pal::IQueue*, QueueRecycleInfo*> queue_pool_; //!< Pool of PAL queues for recycling
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include "device/pal/paldefs.hpp"
|
||||
#include "device/pal/palcapturemgr.hpp"
|
||||
#include "platform/commandqueue.hpp"
|
||||
#include "device/blit.hpp"
|
||||
|
||||
@@ -314,34 +314,36 @@ struct RgpSqttMarkerUserEventWithString {
|
||||
// ================================================================================================
|
||||
// This class provides functionality to interact with the GPU Open Developer Mode message passing
|
||||
// service and the rest of the driver.
|
||||
class RgpCaptureMgr {
|
||||
class RgpCaptureMgr final : public ICaptureMgr {
|
||||
public:
|
||||
~RgpCaptureMgr();
|
||||
|
||||
static RgpCaptureMgr* Create(Pal::IPlatform* platform, const Device& device);
|
||||
|
||||
void Finalize();
|
||||
void PreDispatch(VirtualGPU* gpu, const HSAILKernel& kernel,
|
||||
size_t x, size_t y, size_t z) override;
|
||||
|
||||
void PreDispatch(VirtualGPU* gpu, const HSAILKernel& kernel, size_t x, size_t y, size_t z);
|
||||
void PostDispatch(VirtualGPU* gpu);
|
||||
void PostDispatch(VirtualGPU* gpu) override;
|
||||
|
||||
void WaitForDriverResume();
|
||||
|
||||
void PostDeviceCreate();
|
||||
void PreDeviceDestroy();
|
||||
void FinishRGPTrace(VirtualGPU* gpu, bool aborted);
|
||||
|
||||
bool IsQueueTimingActive() const;
|
||||
void FinishRGPTrace(VirtualGPU* gpu, bool aborted) override;
|
||||
|
||||
void WriteBarrierStartMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const;
|
||||
void WriteBarrierEndMarker(const VirtualGPU* gpu, const Pal::Developer::BarrierData& data) const;
|
||||
bool RegisterTimedQueue(uint32_t queue_id, Pal::IQueue* iQueue, bool* debug_vmid) const;
|
||||
const Pal::Developer::BarrierData& data) const override;
|
||||
|
||||
void WriteBarrierEndMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const override;
|
||||
|
||||
bool RegisterTimedQueue(uint32_t queue_id,
|
||||
Pal::IQueue* iQueue, bool* debug_vmid) const override;
|
||||
|
||||
Pal::Result TimedQueueSubmit(Pal::IQueue* queue, uint64_t cmdId,
|
||||
const Pal::SubmitInfo& submitInfo) const;
|
||||
bool Update(Pal::IPlatform* platform);
|
||||
uint64_t AddElfBinary(const void* exe_binary, size_t exe_binary_size, const void* elf_binary,
|
||||
size_t elf_binary_size, Pal::IGpuMemory* pGpuMemory, size_t offset);
|
||||
const Pal::SubmitInfo& submitInfo) const override;
|
||||
|
||||
bool Update(Pal::IPlatform* platform) override;
|
||||
|
||||
uint64_t AddElfBinary(const void* exe_binary, size_t exe_binary_size,
|
||||
const void* elf_binary, size_t elf_binary_size,
|
||||
Pal::IGpuMemory* pGpuMemory, size_t offset) override;
|
||||
private:
|
||||
// Steps that an RGP trace goes through
|
||||
enum class TraceStatus {
|
||||
@@ -375,6 +377,8 @@ class RgpCaptureMgr {
|
||||
RgpCaptureMgr(Pal::IPlatform* platform, const Device& device);
|
||||
|
||||
bool Init(Pal::IPlatform* platform);
|
||||
void Finalize();
|
||||
|
||||
Pal::Result PrepareRGPTrace(VirtualGPU* pQueue);
|
||||
Pal::Result BeginRGPTrace(VirtualGPU* pQueue);
|
||||
Pal::Result EndRGPHardwareTrace(VirtualGPU* pQueue);
|
||||
@@ -382,6 +386,7 @@ class RgpCaptureMgr {
|
||||
void DestroyRGPTracing();
|
||||
Pal::Result CheckForTraceResults();
|
||||
static bool GpuSupportsTracing(const Pal::DeviceProperties& props, const Settings& settings);
|
||||
|
||||
RgpSqttMarkerEvent BuildEventMarker(const VirtualGPU* gpu, RgpSqttMarkerEventType api_type) const;
|
||||
void WriteMarker(const VirtualGPU* gpu, const void* data, size_t data_size) const;
|
||||
void WriteEventWithDimsMarker(const VirtualGPU* gpu, RgpSqttMarkerEventType apiType, uint32_t x,
|
||||
@@ -390,6 +395,13 @@ class RgpCaptureMgr {
|
||||
const std::string& name) const;
|
||||
void WriteComputeBindMarker(const VirtualGPU* gpu, uint64_t api_hash) const;
|
||||
|
||||
void WaitForDriverResume();
|
||||
|
||||
void PostDeviceCreate();
|
||||
void PreDeviceDestroy();
|
||||
|
||||
bool IsQueueTimingActive() const;
|
||||
|
||||
const Device& device_;
|
||||
DevDriver::DevDriverServer* dev_driver_server_;
|
||||
DevDriver::RGPProtocol::RGPServer* rgp_server_;
|
||||
|
||||
@@ -804,8 +804,8 @@ bool LightningProgram::setKernels(void* binary, size_t binSize, amd::Os::FileDes
|
||||
size_t foffset, std::string uri) {
|
||||
#if defined(USE_COMGR_LIBRARY)
|
||||
// Collect the information about compiled binary, except the trap handler
|
||||
if (!isNull() && (palDevice().rgpCaptureMgr() != nullptr) && !isTrapHandler()) {
|
||||
apiHash_ = palDevice().rgpCaptureMgr()->AddElfBinary(
|
||||
if (!isNull() && (palDevice().captureMgr() != nullptr) && !isTrapHandler()) {
|
||||
apiHash_ = palDevice().captureMgr()->AddElfBinary(
|
||||
binary, binSize, binary, binSize, codeSegGpu_->iMem(), codeSegGpu_->offset());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/* Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "device/pal/palubercapturemgr.hpp"
|
||||
#include "device/pal/paldevice.hpp"
|
||||
|
||||
#include "palPlatform.h"
|
||||
#include "palTraceSession.h"
|
||||
#include "palRenderOpTraceController.h"
|
||||
#include "palCodeObjectTraceSource.h"
|
||||
#include "palQueueTimingsTraceSource.h"
|
||||
|
||||
#include "devDriverServer.h"
|
||||
#include "protocols/driverControlServer.h"
|
||||
#include "util/ddStructuredReader.h"
|
||||
|
||||
namespace amd::pal {
|
||||
|
||||
// ================================================================================================
|
||||
// Returns true if the given device properties/settings support tracing.
|
||||
static inline bool GpuSupportsTracing(const Pal::DeviceProperties& props,
|
||||
const Settings& settings) {
|
||||
return props.gfxipProperties.flags.supportRgpTraces && !settings.rgpSqttForceDisable_;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// Creates the GPU Open Developer Mode manager class.
|
||||
UberTraceCaptureMgr* UberTraceCaptureMgr::Create(Pal::IPlatform* platform, const Device& device) {
|
||||
UberTraceCaptureMgr* mgr = new UberTraceCaptureMgr(platform, device);
|
||||
|
||||
if (mgr != nullptr && !mgr->Init(platform)) {
|
||||
delete mgr;
|
||||
mgr = nullptr;
|
||||
}
|
||||
|
||||
return mgr;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
UberTraceCaptureMgr::UberTraceCaptureMgr(Pal::IPlatform* platform, const Device& device)
|
||||
: device_(device),
|
||||
dev_driver_server_(platform->GetDevDriverServer()),
|
||||
global_disp_count_(1), // Must start from 1 according to RGP spec
|
||||
trace_session_(platform->GetTraceSession()),
|
||||
trace_controller_(nullptr),
|
||||
code_object_trace_source_(nullptr),
|
||||
queue_timings_trace_source_(nullptr) {
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
UberTraceCaptureMgr::~UberTraceCaptureMgr() {
|
||||
DestroyUberTraceResources();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool UberTraceCaptureMgr::CreateUberTraceResources(Pal::IPlatform* platform) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
// Initialize the renderop trace controller
|
||||
trace_controller_ = new GpuUtil::RenderOpTraceController(platform, device_.iDev());
|
||||
if (trace_controller_ == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
Pal::Result result = trace_session_->RegisterController(trace_controller_);
|
||||
if (result != Pal::Result::Success) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize the code object trace source
|
||||
code_object_trace_source_ = new GpuUtil::CodeObjectTraceSource(platform);
|
||||
if (code_object_trace_source_ == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
result = trace_session_->RegisterSource(code_object_trace_source_);
|
||||
if (result != Pal::Result::Success) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize the queue timings trace source
|
||||
queue_timings_trace_source_ = new GpuUtil::QueueTimingsTraceSource(platform);
|
||||
if (queue_timings_trace_source_ == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
result = trace_session_->RegisterSource(queue_timings_trace_source_);
|
||||
if (result != Pal::Result::Success) {
|
||||
break;
|
||||
}
|
||||
|
||||
success = true;
|
||||
} while (false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::DestroyUberTraceResources() {
|
||||
// Deallocate and unregister all created trace controllers & trace sources
|
||||
|
||||
// RenderOp TraceController
|
||||
if (trace_controller_ != nullptr) {
|
||||
trace_session_->UnregisterController(trace_controller_);
|
||||
delete trace_controller_;
|
||||
trace_controller_ = nullptr;
|
||||
}
|
||||
|
||||
// CodeObjects TraceSource
|
||||
if (code_object_trace_source_ != nullptr) {
|
||||
trace_session_->UnregisterSource(code_object_trace_source_);
|
||||
delete code_object_trace_source_;
|
||||
code_object_trace_source_ = nullptr;
|
||||
}
|
||||
|
||||
// QueueTimings TraceSource
|
||||
if (queue_timings_trace_source_ != nullptr) {
|
||||
trace_session_->UnregisterSource(queue_timings_trace_source_);
|
||||
delete queue_timings_trace_source_;
|
||||
queue_timings_trace_source_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool UberTraceCaptureMgr::Init(Pal::IPlatform* platform) {
|
||||
// Finalize the devmode manager
|
||||
if (dev_driver_server_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
dev_driver_server_->Finalize();
|
||||
|
||||
// Initialize the trace sources & controllers owned by the compute driver
|
||||
const bool success = CreateUberTraceResources(platform);
|
||||
|
||||
if (!success) {
|
||||
DestroyUberTraceResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::PreDispatch(VirtualGPU* gpu, const HSAILKernel& kernel,
|
||||
size_t x, size_t y, size_t z) {
|
||||
// Wait for the driver to be resumed in case it's been paused.
|
||||
WaitForDriverResume();
|
||||
|
||||
// Increment dispatch count in RenderOp trace controller
|
||||
Pal::IQueue* pQueue = gpu->queue(MainEngine).iQueue_;
|
||||
trace_controller_->RecordRenderOp(pQueue, GpuUtil::RenderOpTraceController::RenderOpDispatch);
|
||||
|
||||
// Increment the global dispatch counter
|
||||
global_disp_count_++;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::PostDispatch(VirtualGPU* gpu) {
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// Waits for the driver to be resumed if it's currently paused.
|
||||
void UberTraceCaptureMgr::WaitForDriverResume() {
|
||||
auto* pDriverControlServer = dev_driver_server_->GetDriverControlServer();
|
||||
|
||||
assert(pDriverControlServer != nullptr);
|
||||
pDriverControlServer->DriverTick();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::PreDeviceDestroy() {
|
||||
if (trace_session_->GetTraceSessionState() == GpuUtil::TraceSessionState::Ready) {
|
||||
DestroyUberTraceResources();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::FinishRGPTrace(VirtualGPU* gpu, bool aborted) {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool UberTraceCaptureMgr::IsQueueTimingActive() const {
|
||||
return ((queue_timings_trace_source_ != nullptr) &&
|
||||
(queue_timings_trace_source_->IsTimingInProgress()));
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::WriteBarrierStartMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const {
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void UberTraceCaptureMgr::WriteBarrierEndMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const {
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool UberTraceCaptureMgr::RegisterTimedQueue(uint32_t queue_id,
|
||||
Pal::IQueue* iQueue,
|
||||
bool* debug_vmid) const {
|
||||
// Get the OS context handle for this queue (this is a thing that RGP needs on DX clients;
|
||||
// it may be optional for Vulkan, but we provide it anyway if available).
|
||||
Pal::KernelContextInfo kernelContextInfo = {};
|
||||
Pal::Result result = iQueue->QueryKernelContextInfo(&kernelContextInfo);
|
||||
|
||||
// QueryKernelContextInfo may fail.
|
||||
// If so, just use a context identifier of 0.
|
||||
uint64_t queueContext = (result == Pal::Result::Success)
|
||||
? kernelContextInfo.contextIdentifier
|
||||
: 0;
|
||||
|
||||
// Register the queue with the GPA session class for timed queue operation support.
|
||||
result = queue_timings_trace_source_->RegisterTimedQueue(iQueue, queue_id, queueContext);
|
||||
|
||||
return (result == Pal::Result::Success);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
Pal::Result UberTraceCaptureMgr::TimedQueueSubmit(Pal::IQueue* queue, uint64_t cmdId,
|
||||
const Pal::SubmitInfo& submitInfo) const {
|
||||
// Fill in extra meta-data information to associate the API command buffer data with
|
||||
// the generated timing information.
|
||||
GpuUtil::TimedSubmitInfo timedSubmitInfo = {};
|
||||
Pal::uint64 apiCmdBufIds = cmdId;
|
||||
Pal::uint32 sqttCmdBufIds = 0;
|
||||
|
||||
timedSubmitInfo.pApiCmdBufIds = &apiCmdBufIds;
|
||||
timedSubmitInfo.pSqttCmdBufIds = &sqttCmdBufIds;
|
||||
timedSubmitInfo.frameIndex = 0;
|
||||
|
||||
// Do a timed submit of all the command buffers
|
||||
Pal::Result result = queue_timings_trace_source_->TimedSubmit(queue,
|
||||
submitInfo,
|
||||
timedSubmitInfo);
|
||||
|
||||
// Punt to non-timed submit if a timed submit fails (or is not supported)
|
||||
if (result != Pal::Result::Success) {
|
||||
result = queue->Submit(submitInfo);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool UberTraceCaptureMgr::Update(Pal::IPlatform* platform) {
|
||||
Pal::Result result = queue_timings_trace_source_->Init(device_.iDev());
|
||||
return (result == Pal::Result::Success);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
uint64_t UberTraceCaptureMgr::AddElfBinary(const void* exe_binary, size_t exe_binary_size,
|
||||
const void* elf_binary, size_t elf_binary_size,
|
||||
Pal::IGpuMemory* pGpuMemory, size_t offset) {
|
||||
GpuUtil::ElfBinaryInfo elfBinaryInfo = {};
|
||||
elfBinaryInfo.pBinary = exe_binary;
|
||||
elfBinaryInfo.binarySize = exe_binary_size; ///< FAT Elf binary size.
|
||||
elfBinaryInfo.pGpuMemory = pGpuMemory; ///< GPU Memory where the compiled ISA resides.
|
||||
elfBinaryInfo.offset = static_cast<Pal::gpusize>(offset);
|
||||
|
||||
elfBinaryInfo.originalHash = DevDriver::MetroHash::MetroHash64(
|
||||
reinterpret_cast<const DevDriver::uint8*>(elf_binary), elf_binary_size);
|
||||
|
||||
elfBinaryInfo.compiledHash = DevDriver::MetroHash::MetroHash64(
|
||||
reinterpret_cast<const DevDriver::uint8*>(exe_binary), exe_binary_size);
|
||||
|
||||
assert(code_object_trace_source_ != nullptr);
|
||||
|
||||
code_object_trace_source_->RegisterElfBinary(elfBinaryInfo);
|
||||
|
||||
return elfBinaryInfo.originalHash;
|
||||
}
|
||||
|
||||
} // namespace amd::pal
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "device/pal/palcapturemgr.hpp"
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
class DevDriverServer;
|
||||
}
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
class TraceSession;
|
||||
class RenderOpTraceController;
|
||||
class CodeObjectTraceSource;
|
||||
class QueueTimingsTraceSource;
|
||||
}
|
||||
|
||||
namespace amd::pal {
|
||||
|
||||
// ================================================================================================
|
||||
class UberTraceCaptureMgr final : public ICaptureMgr {
|
||||
public:
|
||||
static UberTraceCaptureMgr* Create(Pal::IPlatform* platform, const Device& device);
|
||||
|
||||
~UberTraceCaptureMgr();
|
||||
|
||||
bool Update(Pal::IPlatform* platform) override;
|
||||
|
||||
void PreDispatch(VirtualGPU* gpu, const HSAILKernel& kernel,
|
||||
size_t x, size_t y, size_t z) override;
|
||||
|
||||
void PostDispatch(VirtualGPU* gpu) override;
|
||||
|
||||
void FinishRGPTrace(VirtualGPU* gpu, bool aborted) override;
|
||||
|
||||
void WriteBarrierStartMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const override;
|
||||
|
||||
void WriteBarrierEndMarker(const VirtualGPU* gpu,
|
||||
const Pal::Developer::BarrierData& data) const override;
|
||||
|
||||
bool RegisterTimedQueue(uint32_t queue_id,
|
||||
Pal::IQueue* iQueue, bool* debug_vmid) const override;
|
||||
|
||||
Pal::Result TimedQueueSubmit(Pal::IQueue* queue, uint64_t cmdId,
|
||||
const Pal::SubmitInfo& submitInfo) const override;
|
||||
|
||||
uint64_t AddElfBinary(const void* exe_binary, size_t exe_binary_size,
|
||||
const void* elf_binary, size_t elf_binary_size,
|
||||
Pal::IGpuMemory* pGpuMemory, size_t offset) override;
|
||||
private:
|
||||
UberTraceCaptureMgr(Pal::IPlatform* platform, const Device& device);
|
||||
bool Init(Pal::IPlatform* platform);
|
||||
void WaitForDriverResume();
|
||||
|
||||
void PreDeviceDestroy();
|
||||
|
||||
bool IsQueueTimingActive() const;
|
||||
|
||||
bool CreateUberTraceResources(Pal::IPlatform* platform);
|
||||
void DestroyUberTraceResources();
|
||||
|
||||
const Device& device_;
|
||||
DevDriver::DevDriverServer* dev_driver_server_;
|
||||
uint64_t global_disp_count_;
|
||||
|
||||
GpuUtil::TraceSession* trace_session_;
|
||||
GpuUtil::RenderOpTraceController* trace_controller_;
|
||||
GpuUtil::CodeObjectTraceSource* code_object_trace_source_;
|
||||
GpuUtil::QueueTimingsTraceSource* queue_timings_trace_source_;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(UberTraceCaptureMgr);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(UberTraceCaptureMgr);
|
||||
};
|
||||
|
||||
} // namespace amd::pal
|
||||
@@ -422,7 +422,7 @@ bool VirtualGPU::Queue::flush() {
|
||||
// Submit command buffer to OS
|
||||
Pal::Result result;
|
||||
if (gpu_.rgpCaptureEna()) {
|
||||
result = gpu_.dev().rgpCaptureMgr()->TimedQueueSubmit(iQueue_, cmdBufIdCurrent_, submitInfo);
|
||||
result = gpu_.dev().captureMgr()->TimedQueueSubmit(iQueue_, cmdBufIdCurrent_, submitInfo);
|
||||
} else {
|
||||
result = iQueue_->Submit(submitInfo);
|
||||
}
|
||||
@@ -1025,12 +1025,11 @@ bool VirtualGPU::create(bool profiling, uint deviceQueueSize, uint rtCUs,
|
||||
|
||||
// If the developer mode manager is available and it's not a device queue,
|
||||
// then enable RGP capturing
|
||||
if ((index() != 0) && dev().rgpCaptureMgr() != nullptr) {
|
||||
if ((index() != 0) && dev().captureMgr() != nullptr) {
|
||||
bool dbg_vmid = false;
|
||||
state_.rgpCaptureEnabled_ = true;
|
||||
dev().rgpCaptureMgr()->RegisterTimedQueue(2 * index(), queue(MainEngine).iQueue_, &dbg_vmid);
|
||||
dev().rgpCaptureMgr()->RegisterTimedQueue(2 * index() + 1, queue(SdmaEngine).iQueue_,
|
||||
&dbg_vmid);
|
||||
dev().captureMgr()->RegisterTimedQueue(2 * index(), queue(MainEngine).iQueue_, &dbg_vmid);
|
||||
dev().captureMgr()->RegisterTimedQueue(2 * index() + 1, queue(SdmaEngine).iQueue_, &dbg_vmid);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1076,7 +1075,7 @@ VirtualGPU::~VirtualGPU() {
|
||||
|
||||
// Destroy RGP trace
|
||||
if (rgpCaptureEna()) {
|
||||
dev().rgpCaptureMgr()->FinishRGPTrace(this, true);
|
||||
dev().captureMgr()->FinishRGPTrace(this, true);
|
||||
}
|
||||
|
||||
while (!freeCbQueue_.empty()) {
|
||||
@@ -2575,7 +2574,7 @@ bool VirtualGPU::submitKernelInternal(const amd::NDRangeContainer& sizes,
|
||||
newLocalSize[i] = sizes.local()[i];
|
||||
}
|
||||
}
|
||||
dev().rgpCaptureMgr()->PreDispatch(
|
||||
dev().captureMgr()->PreDispatch(
|
||||
this, hsaKernel,
|
||||
// Report global size in workgroups, since that's the RGP trace semantics
|
||||
newGlobalSize[0] / newLocalSize[0], newGlobalSize[1] / newLocalSize[1],
|
||||
@@ -2758,7 +2757,7 @@ bool VirtualGPU::submitKernelInternal(const amd::NDRangeContainer& sizes,
|
||||
|
||||
// Perform post dispatch logic for RGP traces
|
||||
if (rgpCaptureEna()) {
|
||||
dev().rgpCaptureMgr()->PostDispatch(this);
|
||||
dev().captureMgr()->PostDispatch(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user