From 844ad312f85ceba1e1f7f72db132ff32fed25760 Mon Sep 17 00:00:00 2001 From: foreman Date: Thu, 21 Jul 2016 10:32:54 -0400 Subject: [PATCH] P4 to Git Change 1293980 by jatang@jatang-opencl-hsa-stg3 on 2016/07/21 10:22:49 SWDEV-95919 - OCL ThreadTrace on PAL. The PAL PerfExperiment interface is not compatible with the OCL ThreadTrace extension, in terms of Thread Trace buffer handling. PAL PerfExperiment is expecting one buffer bound to it for all shader engines, while the OCL ThreadTrace extension is expecting one buffer for each shader engines. To accomodate the difference, we copy from the PAL PerfExperiment buffer to the OCL ThreadTrace extension buffers. The next step is to support setting ThreadTrace parameters, and getting actually capture size from the layout. Affected files ... ... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palthreadtrace.cpp#2 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palthreadtrace.hpp#3 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palvirtual.cpp#18 edit [ROCm/clr commit: 892bda4554bdba7116b8bca46fdf58849ee9e26a] --- .../runtime/device/pal/palthreadtrace.cpp | 149 ++++++++++++++++-- .../runtime/device/pal/palthreadtrace.hpp | 124 +++++++-------- .../rocclr/runtime/device/pal/palvirtual.cpp | 86 +++------- 3 files changed, 210 insertions(+), 149 deletions(-) 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; }