diff --git a/projects/clr/rocclr/runtime/device/pal/palthreadtrace.cpp b/projects/clr/rocclr/runtime/device/pal/palthreadtrace.cpp index 871e1de8f5..7370f24e6b 100644 --- a/projects/clr/rocclr/runtime/device/pal/palthreadtrace.cpp +++ b/projects/clr/rocclr/runtime/device/pal/palthreadtrace.cpp @@ -1,59 +1,174 @@ // // Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved. // + #include "device/pal/palthreadtrace.hpp" #include "device/pal/palvirtual.hpp" namespace pal { -CalThreadTraceReference::~CalThreadTraceReference() { +PalThreadTraceReference* +PalThreadTraceReference::Create(VirtualGPU& gpu) +{ + Pal::Result result; + + // Create performance experiment + Pal::PerfExperimentCreateInfo createInfo = {}; + + createInfo.optionFlags.sampleInternalOperations = 1; + createInfo.optionFlags.cacheFlushOnCounterCollection = 1; + createInfo.optionFlags.sqShaderMask = 1; + createInfo.optionValues.sampleInternalOperations = true; + createInfo.optionValues.cacheFlushOnCounterCollection = true; + createInfo.optionValues.sqShaderMask = Pal::PerfShaderMaskCs; + + size_t palExperSize = gpu.dev().iDev()->GetPerfExperimentSize( + createInfo, &result); + if (result != Pal::Result::Success) { + return nullptr; + } + + PalThreadTraceReference* memRef = new (palExperSize) PalThreadTraceReference(gpu); + if (memRef != nullptr) { + result = gpu.dev().iDev()->CreatePerfExperiment(createInfo, + &memRef[1], &memRef->perfExp_); + if (result != Pal::Result::Success) { + memRef->release(); + return nullptr; + } + } + + return memRef; +} + +PalThreadTraceReference::~PalThreadTraceReference() +{ // The thread trace object is always associated with a particular queue, // so we have to lock just this queue amd::ScopedLock lock(gpu_.execution()); - if (0 != threadTrace_) { - //gpu().cs()->destroyQuery(gslThreadTrace()); + delete layout_; + delete memory_; + + if (nullptr != iPerf()) { + iPerf()->Destroy(); } } +bool +PalThreadTraceReference::finalize() +{ + Pal::Result result; + + iPerf()->Finalize(); + + // Acquire GPU memory for the query from the pool and bind it. + Pal::GpuMemoryRequirements gpuMemReqs = {}; + iPerf()->GetGpuMemoryRequirements(&gpuMemReqs); + + memory_ = new Memory(gpu().dev(), amd::alignUp(gpuMemReqs.size, gpuMemReqs.alignment)); + + if (nullptr == memory_) { + return false; + } + + if (!memory_->create(Resource::Local)) { + return false; + } + + gpu_.queue(gpu_.engineID_).addMemRef(memory_->iMem()); + + result = iPerf()->BindGpuMemory(memory_->iMem(), 0); + + if (result != Pal::Result::Success) { + return false; + } + + Pal::ThreadTraceLayout layout = {}; + iPerf()->GetThreadTraceLayout(&layout); + + size_t size = sizeof(Pal::ThreadTraceLayout) + (sizeof(Pal::ThreadTraceSeLayout) * (layout.traceCount - 1)); + layout_ = reinterpret_cast(new char[size]); + if (layout_ == nullptr) { + return false; + } + + layout_->traceCount = layout.traceCount; + iPerf()->GetThreadTraceLayout(layout_); + + return true; +} + +void +PalThreadTraceReference::copyToUserBuffer(Memory* dstMem, uint seIndex) +{ + amd::Coord3D srcOrigin(layout_->traces[seIndex].dataOffset, 0, 0); + amd::Coord3D dstOrigin(0, 0, 0); + amd::Coord3D size(dstMem->size(), 0, 0); + + gpu_.blitMgr().copyBuffer(*memory_, *dstMem, srcOrigin, dstOrigin, size, true); +} + ThreadTrace::~ThreadTrace() { - if (calRef_ == nullptr) { + if (palRef_ == nullptr) { return; } - Unimplemented(); - for(uint i = 0; i < amdThreadTraceMemObjsNum_;++i) { -// threadTraceBufferObjs_[i]->attachMemObject(gpu().cs(), nullptr, 0, 0, 0, i); -// gpu().cs()->destroyShaderTraceBuffer(threadTraceBufferObjs_[i]); - } // Release the thread trace reference object - //calRef_->release(); + palRef_->release(); } bool -ThreadTrace::create(CalThreadTraceReference* calRef) +ThreadTrace::create() { - assert(&gpu() == &calRef->gpu()); + palRef_->retain(); - calRef_ = calRef; - threadTrace_ = calRef->gslThreadTrace(); + size_t se = 0; + for (auto itMemObj = memObj_.begin(); itMemObj != memObj_.end(); ++itMemObj, ++se) { + // Initialize the thread trace + Pal::PerfTraceInfo sqttInfo = {}; + sqttInfo.traceType = Pal::PerfTraceType::ThreadTrace; + sqttInfo.instance = se; + + sqttInfo.optionFlags.bufferSize = 1; + // PAL requires ThreadTrace buffer aligned to 4KB + sqttInfo.optionValues.bufferSize = amd::alignUp(dev().getGpuMemory(*itMemObj)->size(), (0x1 << 12)); + sqttInfo.optionFlags.threadTraceTokenMask = 1; + sqttInfo.optionValues.threadTraceTokenMask = 0x0000ffff; + + Pal::Result result = iPerf()->AddTrace(sqttInfo); + if (result != Pal::Result::Success) { + return false; + } + } return true; } +void +ThreadTrace::populateUserMemory() +{ + uint se = 0; + for (auto itMemObj = memObj_.begin(); itMemObj != memObj_.end(); ++itMemObj, ++se) { + palRef_->copyToUserBuffer(dev().getGpuMemory(*itMemObj), se); + } +} + bool ThreadTrace::info(uint infoType, uint* info, uint infoSize) const { switch (infoType) { case CL_THREAD_TRACE_BUFFERS_SIZE: { - if (infoSize < amdThreadTraceMemObjsNum_) { + if (infoSize < numSe_) { LogError("The amount of buffers should be equal to the amount of Shader Engines"); return false; } else { - Unimplemented(); - //gslThreadTrace()->GetResultAll(gpu().cs(), info); + uint se = 0; + for (auto itMemObj = memObj_.begin(); itMemObj != memObj_.end(); ++itMemObj, ++se) { + info[se] = dev().getGpuMemory(*itMemObj)->size(); + } } break; } diff --git a/projects/clr/rocclr/runtime/device/pal/palthreadtrace.hpp b/projects/clr/rocclr/runtime/device/pal/palthreadtrace.hpp index 40fcf76df2..929072670a 100644 --- a/projects/clr/rocclr/runtime/device/pal/palthreadtrace.hpp +++ b/projects/clr/rocclr/runtime/device/pal/palthreadtrace.hpp @@ -13,35 +13,47 @@ namespace pal { class VirtualGPU; -class CalThreadTraceReference : public amd::ReferenceCountedObject +class PalThreadTraceReference : public amd::ReferenceCountedObject { public: - //! Default constructor - CalThreadTraceReference( - VirtualGPU& gpu, //!< Virtual GPU device object - Pal::IPerfExperiment* gslThreadTrace) //!< GSL query thread trace object - : gpu_(gpu) - , threadTrace_(gslThreadTrace){} + static PalThreadTraceReference* Create(VirtualGPU& gpu); - //! Get GSL thread race object - Pal::IPerfExperiment* gslThreadTrace() const { return threadTrace_; } + //! Default constructor + PalThreadTraceReference( + VirtualGPU& gpu //!< Virtual GPU device object + ) + : perfExp_(nullptr) + , gpu_(gpu) + , memory_(nullptr) + , layout_(nullptr) {} + + //! Get PAL thread race object + Pal::IPerfExperiment* iPerf() const { return perfExp_; } //! Returns the virtual GPU device const VirtualGPU& gpu() const { return gpu_; } + //! Prepare for execution + bool finalize(); + + //! Copy ThreadTrace capture to User Buffer + void copyToUserBuffer(Memory* dstMem, uint seIndex); + protected: //! Default destructor - ~CalThreadTraceReference(); + ~PalThreadTraceReference(); private: //! Disable copy constructor - CalThreadTraceReference(const CalThreadTraceReference&); + PalThreadTraceReference(const PalThreadTraceReference&); //! Disable operator= - CalThreadTraceReference& operator=(const CalThreadTraceReference&); + PalThreadTraceReference& operator=(const PalThreadTraceReference&); - VirtualGPU& gpu_; //!< The virtual GPU device object - Pal::IPerfExperiment* threadTrace_; //!< GSL thread trace query object + VirtualGPU& gpu_; //!< The virtual GPU device object + Pal::IPerfExperiment* perfExp_; //!< PAL performance experiment object + Pal::ThreadTraceLayout* layout_; //!< Layout of the result + Memory* memory_; //!< Memory bound to PerfExperiment }; //! ThreadTrace implementation on GPU @@ -49,37 +61,29 @@ class ThreadTrace : public device::ThreadTrace { public: + //! Constructor for the GPU ThreadTrace object + ThreadTrace( + Device& device, //!< A GPU device object + PalThreadTraceReference* palRef, //!< Reference ThreadTrace + const std::vector& memObjs, //!< ThreadTrace memory objects + uint numSe //!< Number of Shader Engines + ) + : gpuDevice_(device) + , palRef_(palRef) + , memObj_(memObjs) + , numSe_(numSe) + { + + } + //! Destructor for the GPU ThreadTrace object virtual ~ThreadTrace(); //! Creates the current object - bool create( - CalThreadTraceReference* calRef //!< Reference ThreadTrace - ); + bool create(); - //! Returns the GPU device, associated with the current object - const Device& dev() const { return gpuDevice_; } - - //! Returns the virtual GPU device - const VirtualGPU& gpu() const { return gpu_; } - - //! Constructor for the GPU ThreadTrace object - ThreadTrace( - Device& device, //!< A GPU device object - VirtualGPU& gpu, //!< Virtual GPU device object - uint amdThreadTraceMemObjsNum) - : gpuDevice_(device) - , gpu_(gpu) - , calRef_(NULL) - , index_(0) - , amdThreadTraceMemObjsNum_(amdThreadTraceMemObjsNum) - { - threadTraceBufferObjs_ = new Pal::ThreadTraceLayout[amdThreadTraceMemObjsNum]; - Unimplemented(); - for (uint i = 0; i < amdThreadTraceMemObjsNum;++i) { - //threadTraceBufferObjs_[i] = gpu.cs()->createShaderTraceBuffer(); - } - } + // Populate ThreadTrace memory with PerfExperiment memory + void populateUserMemory(); //! Returns the specific information about the thread trace object bool info( @@ -88,25 +92,18 @@ public: uint infoSize //!< The size of returned information ) const; - //! Set the ThreadTrace memory buffer size - void setMemBufferSizeTT(uint memBufferSizeTT) { memBufferSizeTT_ = memBufferSizeTT;} - //! Set isNewBufferBinded_ to true/false if new buffer was binded/unbinded respectively - void setNewBufferBinded(bool isNewBufferBinded) { isNewBufferBinded_ = isNewBufferBinded; } + void setNewBufferBinded(bool isNewBufferBinded) {} - //! Attach Pal::IGpuMemory to the TreadTrace buffer - void attachMemToThreadTraceBuffer(); + //! Returns the GPU device, associated with the current object + const Device& dev() const { return gpuDevice_; } - void setMemObj(size_t memObjSize,std::vector memObj) - { - memObj_ = memObj; - memBufferSizeTT_ = memObjSize; - } - //! Get GSL thread trace object - Pal::IPerfExperiment* gslThreadTrace() const { return threadTrace_; } + //! Returns the virtual GPU device + const VirtualGPU& gpu() const { return palRef_->gpu(); } + + //! Get PAL thread trace object + Pal::IPerfExperiment* iPerf() const { return palRef_->iPerf(); } - //! Get GSL Thread Trace Buffer objects - Pal::ThreadTraceLayout* getThreadTraceBufferObjects() {return threadTraceBufferObjs_;} private: //! Disable default copy constructor ThreadTrace(const ThreadTrace&); @@ -114,19 +111,10 @@ private: //! Disable default operator= ThreadTrace& operator=(const ThreadTrace&); - const Device& gpuDevice_; //!< The backend device - - VirtualGPU& gpu_; //!< The virtual GPU device object - - CalThreadTraceReference* calRef_; //!< Reference ThreadTrace - Pal::ThreadTraceLayout* threadTraceBufferObjs_; //!< The buffer object for Thread Trace recording - uint index_; //!< ThreadTrace index in the CAL container - uint memBufferSizeTT_; //!< ThreadTrace memory buffer size - std::vector memObj_; //!< ThreadTrace memory object - Pal::IPerfExperiment* threadTrace_; //!< GSL thread trace query object - uint amdThreadTraceMemObjsNum_; //!< ThreadTrace memory object`s number (should be equal to the SE number) - bool isNewBufferBinded_; //!< The indicator if new buffer was binded to the ThreadTrace object - bool isBufferOnSubmit_; //!< The indicator if "new buffer on submit" mode is used + const Device& gpuDevice_; //!< The backend device + PalThreadTraceReference* palRef_; //!< Reference ThreadTrace + uint numSe_; //!< Number of Shader Engines + std::vector memObj_; //!< ThreadTrace memory objects }; } // namespace pal diff --git a/projects/clr/rocclr/runtime/device/pal/palvirtual.cpp b/projects/clr/rocclr/runtime/device/pal/palvirtual.cpp index 88cd742daa..3ff86e744d 100644 --- a/projects/clr/rocclr/runtime/device/pal/palvirtual.cpp +++ b/projects/clr/rocclr/runtime/device/pal/palvirtual.cpp @@ -2399,34 +2399,29 @@ VirtualGPU::submitThreadTraceMemObjects(amd::ThreadTraceMemObjectsCommand& cmd) amd::ThreadTrace* amdThreadTrace = &cmd.getThreadTrace(); ThreadTrace* threadTrace = static_cast(amdThreadTrace->getDeviceThreadTrace()); - Unimplemented(); -/* + if (threadTrace == nullptr) { - gslQueryObject gslThreadTrace; - // Create a HW thread trace query object - gslThreadTrace = cs()->createQuery(GSL_SHADER_TRACE_BYTES_WRITTEN); - if (0 == gslThreadTrace) { - LogError("Failure in memory allocation for the GPU threadtrace"); - cmd.setStatus(CL_INVALID_OPERATION); - return; - } - CalThreadTraceReference* palRef = new CalThreadTraceReference(*this,gslThreadTrace); + PalThreadTraceReference* palRef = PalThreadTraceReference::Create(*this); if (palRef == nullptr) { LogError("Failure in memory allocation for the GPU threadtrace"); cmd.setStatus(CL_INVALID_OPERATION); return; } - size_t seNum = amdThreadTrace->deviceSeNumThreadTrace(); + + size_t numSe = amdThreadTrace->deviceSeNumThreadTrace(); + ThreadTrace* gpuThreadTrace = new ThreadTrace( gpuDevice_, - *this, - seNum); + palRef, + cmd.getMemList(), + numSe); if (nullptr == gpuThreadTrace) { LogError("Failure in memory allocation for the GPU threadtrace"); cmd.setStatus(CL_INVALID_OPERATION); return; } - if (gpuThreadTrace->create(palRef)) { + + if (gpuThreadTrace->create()) { amdThreadTrace->setDeviceThreadTrace(gpuThreadTrace); } else { @@ -2435,21 +2430,11 @@ VirtualGPU::submitThreadTraceMemObjects(amd::ThreadTraceMemObjectsCommand& cmd) cmd.setStatus(CL_INVALID_OPERATION); return; } - threadTrace = gpuThreadTrace; + + palRef->finalize(); palRef->release(); } - gslShaderTraceBufferObject* threadTraceBufferObjects = threadTrace->getThreadTraceBufferObjects(); - const size_t memObjSize = cmd.getMemoryObjectSize(); - const std::vector& memObj = cmd.getMemList(); - size_t se = 0; - for (std::vector::const_iterator itMemObj = memObj.begin();itMemObj != memObj.end();++itMemObj,++se) { - // Find GSL Mem Object - Pal::IGpuMemory* gslMemObj = dev().getGpuMemory(*itMemObj)->iMem(); - // Bind GSL MemObject to the appropriate SE Thread Trace Buffer Object - threadTraceBufferObjects[se]->attachMemObject(cs(), gslMemObj, 0, 0, memObjSize, se); - } -*/ break; } default: @@ -2480,53 +2465,26 @@ VirtualGPU::submitThreadTrace(amd::ThreadTraceCommand& cmd) return; } else { - Unimplemented(); -/* - gslQueryObject gslThreadTrace; - gslThreadTrace = threadTrace->gslThreadTrace(); - uint32_t seNum = amdThreadTrace->deviceSeNumThreadTrace(); - - // Find the state and sends the commands to GSL + Pal::IPerfExperiment* palPerf = threadTrace->iPerf(); if (cmd.getState() == amd::ThreadTraceCommand::Begin) { amd::ThreadTrace::ThreadTraceConfig* traceCfg = static_cast(cmd.threadTraceConfig()); - const gslErrorCode ec = gslThreadTrace->BeginQuery(cs(), - GSL_SHADER_TRACE_BYTES_WRITTEN, 0); - assert(ec == GSL_NO_ERROR); - - for (uint32_t idx = 0; idx < seNum; ++idx) { - rs()->enableShaderTrace(cs(), idx, true); - rs()->setShaderTraceComputeUnit (idx, traceCfg->cu_); - rs()->setShaderTraceShaderArray (idx, traceCfg->sh_); - rs()->setShaderTraceSIMDMask (idx, traceCfg->simdMask_); - rs()->setShaderTraceVmIdMask (idx, traceCfg->vmIdMask_); - rs()->setShaderTraceTokenMask (idx, traceCfg->tokenMask_); - rs()->setShaderTraceRegisterMask(idx, traceCfg->regMask_); - rs()->setShaderTraceIssueMask (idx, traceCfg->instMask_); - rs()->setShaderTraceRandomSeed (idx, traceCfg->randomSeed_); - rs()->setShaderTraceCaptureMode (idx, traceCfg->captureMode_); - rs()->setShaderTraceWrap (idx, traceCfg->isWrapped_); - rs()->setShaderTraceUserData (idx, - (traceCfg->isUserData_) ? traceCfg->userData_ : 0); - } + iCmd()->CmdBeginPerfExperiment(palPerf); } else if (cmd.getState() == amd::ThreadTraceCommand::End) { - for (uint32_t idx = 0; idx < seNum; ++idx) { - rs()->enableShaderTrace(cs(), idx, false); - } - gslThreadTrace->EndQuery(cs(), 0); + GpuEvent event; + eventBegin(MainEngine); + iCmd()->CmdEndPerfExperiment(palPerf); + threadTrace->populateUserMemory(); + eventEnd(MainEngine, event); + setGpuEvent(event); } else if (cmd.getState() == amd::ThreadTraceCommand::Pause) { - for (uint32_t idx = 0; idx < seNum; ++idx) { - rs()->setShaderTraceIsPaused(cs(), idx, true); - } + // There's no Pause from the PerfExperiment interface } else if (cmd.getState() == amd::ThreadTraceCommand::Resume) { - for (uint32_t idx = 0; idx < seNum; ++idx) { - rs()->setShaderTraceIsPaused(cs(), idx, false); - } + // There's no Resume from the PerfExperiment interface } -*/ } break; }