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: 892bda4554]
这个提交包含在:
foreman
2016-07-21 10:32:54 -04:00
父节点 f035156f1d
当前提交 844ad312f8
修改 3 个文件,包含 210 行新增149 行删除
@@ -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<Pal::ThreadTraceLayout*>(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;
}
@@ -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<amd::Memory*>& 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<amd::Memory*> 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<amd::Memory*> 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<amd::Memory*> memObj_; //!< ThreadTrace memory objects
};
} // namespace pal
@@ -2399,34 +2399,29 @@ VirtualGPU::submitThreadTraceMemObjects(amd::ThreadTraceMemObjectsCommand& cmd)
amd::ThreadTrace* amdThreadTrace = &cmd.getThreadTrace();
ThreadTrace* threadTrace =
static_cast<ThreadTrace*>(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<amd::Memory*>& memObj = cmd.getMemList();
size_t se = 0;
for (std::vector<amd::Memory*>::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<amd::ThreadTrace::ThreadTraceConfig*>(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;
}