P4 to Git Change 1332373 by gandryey@gera-w8 on 2016/10/26 17:21:42

SWDEV-86035 - Add PAL backend to OpenCL
	- Restructure loader functionality

Affected files ...

... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palkernel.cpp#20 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.cpp#16 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.hpp#11 edit


[ROCm/clr commit: 7405502f65]
Αυτή η υποβολή περιλαμβάνεται σε:
foreman
2016-10-26 17:42:37 -04:00
γονέας 6b00dbc18e
υποβολή 1e35d7aa2a
3 αρχεία άλλαξαν με 168 προσθήκες και 228 διαγραφές
@@ -1070,7 +1070,7 @@ HSAILKernel::loadArguments(
else if ((dev().info().svmCapabilities_ & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM) == 0) {
return nullptr;
}
break;
continue;
}
if (nativeMem) {
gpuMem = *reinterpret_cast<Memory* const*>(paramaddr);
@@ -1179,7 +1179,6 @@ HSAILKernel::loadArguments(
assert(arg->size_ == sizeof(srd) && "check the sizes");
WriteAqlArg(&aqlArgBuf, &srd, sizeof(srd));
srdResource = true;
break;
}
else if (arg->type_ == HSAIL_ARGTYPE_QUEUE) {
const amd::DeviceQueue* queue =
@@ -1198,7 +1197,6 @@ HSAILKernel::loadArguments(
}
assert(arg->size_ == sizeof(vmQueue) && "check the sizes");
WriteAqlArg(&aqlArgBuf, &vmQueue, sizeof(vmQueue));
break;
}
else {
LogError(" Unsupported address type ");
@@ -28,6 +28,107 @@
namespace pal {
Segment::Segment()
: gpuAccess_(nullptr)
, cpuAccess_(nullptr)
{}
Segment::~Segment()
{
delete gpuAccess_;
if (cpuAccess_ != nullptr) {
cpuAccess_->unmap(nullptr);
delete cpuAccess_;
}
}
bool
Segment::alloc(
HSAILProgram& prog, amdgpu_hsa_elf_segment_t segment,
size_t size, size_t align, bool zero)
{
align = amd::alignUp(align, sizeof(uint32_t));
gpuAccess_ = new pal::Memory(prog.dev(), amd::alignUp(size, align));
if ((gpuAccess_ == nullptr) || !gpuAccess_->create(pal::Resource::Local)) {
delete gpuAccess_;
gpuAccess_ = nullptr;
return false;
}
if (segment == AMDGPU_HSA_SEGMENT_CODE_AGENT) {
cpuAccess_ = new pal::Memory(prog.dev(), amd::alignUp(size, align));
if ((cpuAccess_ == nullptr) || !cpuAccess_->create(pal::Resource::Remote)) {
delete cpuAccess_;
cpuAccess_ = nullptr;
return false;
}
void* ptr = cpuAccess_->map(nullptr, 0);
if (zero) {
memset(ptr, 0, size);
}
}
if (zero && !prog.isInternal()) {
char pattern = 0;
prog.dev().xferMgr().fillBuffer(*gpuAccess_, &pattern, sizeof(pattern),
amd::Coord3D(0), amd::Coord3D(size));
}
switch (segment) {
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT:
prog.addGlobalStore(gpuAccess_);
prog.setGlobalVariableTotalSize(prog.globalVariableTotalSize() + size);
break;
case AMDGPU_HSA_SEGMENT_CODE_AGENT:
prog.setCodeObjects(gpuAccess_, cpuAccess_->data());
break;
default:
break;
}
return true;
}
void
Segment::copy(size_t offset, const void* src, size_t size)
{
if (cpuAccess_ != nullptr) {
amd::Os::fastMemcpy(cpuAddress(offset), src, size);
}
else {
VirtualGPU& gpu = *gpuAccess_->dev().xferQueue();
Memory& xferBuf = gpuAccess_->dev().xferWrite().acquire();
size_t tmpSize = std::min(static_cast<size_t>(xferBuf.vmSize()), size);
size_t srcOffs = 0;
while (size != 0) {
xferBuf.hostWrite(&gpu,
reinterpret_cast<const_address>(src) + srcOffs, 0, tmpSize);
bool result = xferBuf.partialMemCopyTo(gpu,
0, (offset + srcOffs), tmpSize, *gpuAccess_, false, true);
size -= tmpSize;
srcOffs += tmpSize;
tmpSize = std::min(static_cast<size_t>(xferBuf.vmSize()), size);
}
gpu.releaseMemObjects();
gpu.waitAllEngines();
}
}
bool
Segment::freeze(bool destroySysmem)
{
VirtualGPU& gpu = *gpuAccess_->dev().xferQueue();
bool result = true;
if (cpuAccess_ != nullptr) {
result = cpuAccess_->partialMemCopyTo(gpu,
0, 0, gpuAccess_->vmSize(), *gpuAccess_, false, true);
gpu.releaseMemObjects();
gpu.waitAllEngines();
}
assert(!destroySysmem || (cpuAccess_ == nullptr));
return result;
}
HSAILProgram::HSAILProgram(Device& device)
: Program(device)
, llvmBinary_()
@@ -97,8 +198,6 @@ HSAILProgram::~HSAILProgram()
}
delete kernels_;
amd::hsa::loader::Loader::Destroy(loader_);
assert((codeSegGpu_ == nullptr) && "Loader didn't destroy code!");
assert((codeSegCpu_ == nullptr) && "Loader didn't destroy code!");
}
bool
@@ -786,46 +885,47 @@ bool PALHSALoaderContext::IsaSupportedByAgent(hsa_agent_t agent, hsa_isa_t isa)
}
}
void* PALHSALoaderContext::SegmentAlloc(amdgpu_hsa_elf_segment_t segment,
hsa_agent_t agent, size_t size, size_t align, bool zero) {
void* PALHSALoaderContext::SegmentAlloc(
amdgpu_hsa_elf_segment_t segment,
hsa_agent_t agent, size_t size, size_t align, bool zero)
{
assert(size);
assert(align);
switch (segment) {
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT:
return AgentGlobalAlloc(agent, size, align, zero);
case AMDGPU_HSA_SEGMENT_CODE_AGENT:
return KernelCodeAlloc(size, align, zero);
default:
assert(false); return 0;
if (program_->isNull()) {
void* ptr = amd::Os::alignedMalloc(size, align);
if (zero) {
memset(ptr, 0, size);
}
return ptr;
}
Segment* seg = new Segment();
if (seg != nullptr && !seg->alloc(*program_, segment, size, align, zero)) {
return nullptr;
}
return seg;
}
bool PALHSALoaderContext::SegmentCopy(amdgpu_hsa_elf_segment_t segment,
hsa_agent_t agent, void* dst, size_t offset, const void* src, size_t size) {
switch (segment) {
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT:
return AgentGlobalCopy(dst, offset, src, size);
case AMDGPU_HSA_SEGMENT_CODE_AGENT:
return KernelCodeCopy(dst, offset, src, size);
default:
assert(false); return false;
hsa_agent_t agent, void* dst, size_t offset, const void* src, size_t size)
{
if (program_->isNull()) {
amd::Os::fastMemcpy(reinterpret_cast<address>(dst) + offset, src, size);
return true;
}
Segment* s = reinterpret_cast<Segment*>(dst);
s->copy(offset, src, size);
return true;
}
void PALHSALoaderContext::SegmentFree(
amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t size)
{
switch (segment) {
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT: AgentGlobalFree(seg, size); break;
case AMDGPU_HSA_SEGMENT_CODE_AGENT: KernelCodeFree(seg, size); break;
default:
assert(false); return;
if (program_->isNull()) {
amd::Os::alignedFree(seg);
}
else {
Segment* s = reinterpret_cast<Segment*>(seg);
delete s ;
}
}
@@ -833,65 +933,32 @@ void* PALHSALoaderContext::SegmentAddress(
amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t offset)
{
assert(seg);
switch (segment) {
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT: {
case AMDGPU_HSA_SEGMENT_CODE_AGENT:
if (!program_->isNull()) {
pal::Memory *gpuMem = reinterpret_cast<pal::Memory*>(seg);
return reinterpret_cast<void*>(gpuMem->vmAddress() + offset);
}
else {
return reinterpret_cast<address>(seg) + offset;
}
}
default:
assert(false); return nullptr;
if (program_->isNull()) {
return (reinterpret_cast<address>(seg) + offset);
}
Segment* s = reinterpret_cast<Segment*>(seg);
return reinterpret_cast<void*>(s->gpuAddress(offset));
}
void* PALHSALoaderContext::SegmentHostAddress(
amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t offset)
{
void* host = nullptr;
assert(seg);
switch (segment) {
case AMDGPU_HSA_SEGMENT_CODE_AGENT:
host = program_->codeSegCpu() + offset;
break;
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT:
default:
break;
if (program_->isNull()) {
return (reinterpret_cast<address>(seg) + offset);
}
return host;
Segment* s = reinterpret_cast<Segment*>(seg);
return s ->cpuAddress(offset);
}
bool PALHSALoaderContext::SegmentFreeze(
amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t size)
{
assert(seg);
switch (segment) {
case AMDGPU_HSA_SEGMENT_GLOBAL_PROGRAM:
case AMDGPU_HSA_SEGMENT_GLOBAL_AGENT:
case AMDGPU_HSA_SEGMENT_READONLY_AGENT:
return true;
case AMDGPU_HSA_SEGMENT_CODE_AGENT: {
if (program_->isNull()) {
return true;
}
const pal::Memory& mem = program_->codeSegGpu();
constexpr bool WaitForCopy = true;
mem.writeRawData(*mem.dev().xferQueue(), 0, size, program_->codeSegCpu(), WaitForCopy);
if (program_->isNull()) {
return true;
}
default:
assert(false);
return false;
}
Segment* s = reinterpret_cast<Segment*>(seg);
return s->freeze((segment == AMDGPU_HSA_SEGMENT_CODE_AGENT) ? false : true);
}
hsa_status_t PALHSALoaderContext::SamplerCreate(
@@ -958,122 +1025,6 @@ hsa_status_t PALHSALoaderContext::SamplerDestroy(
return HSA_STATUS_SUCCESS;
}
address PALHSALoaderContext::CpuMemAlloc(size_t size, size_t align, bool zero)
{
assert(size);
assert(align);
assert(sizeof(void*) == 8 || sizeof(void*) == 4);
void* ptr = amd::Os::alignedMalloc(size, align);
if (zero) {
memset(ptr, 0, size);
}
return reinterpret_cast<address>(ptr);
}
bool PALHSALoaderContext::CpuMemCopy(void *dst, size_t offset, const void* src, size_t size)
{
amd::Os::fastMemcpy((char*)dst + offset, src, size);
return true;
}
void* PALHSALoaderContext::GpuMemAlloc(size_t size, size_t align, bool zero) {
assert(size);
assert(align);
assert(sizeof(void*) == 8 || sizeof(void*) == 4);
if (program_->isNull()) {
return CpuMemAlloc(size, align, zero);
}
pal::Memory* mem = new pal::Memory(program_->dev(), amd::alignUp(size, align));
if (!mem || !mem->create(pal::Resource::Local)) {
delete mem;
return nullptr;
}
assert(program_->dev().xferQueue());
if (zero && !program_->isInternal()) {
char pattern = 0;
program_->dev().xferMgr().fillBuffer(*mem, &pattern, sizeof(pattern), amd::Coord3D(0), amd::Coord3D(size));
}
program_->addGlobalStore(mem);
program_->setGlobalVariableTotalSize(program_->globalVariableTotalSize() + size);
return mem;
}
bool PALHSALoaderContext::GpuMemCopy(void *dst, size_t offset, const void *src, size_t size) {
if (!dst || !src || dst == src) {
return false;
}
if (0 == size) {
return true;
}
if (program_->isNull()) {
CpuMemCopy(dst, offset, src, size);
return true;
}
assert(program_->dev().xferQueue());
pal::Memory* mem = reinterpret_cast<pal::Memory*>(dst);
constexpr bool WaitForCopy = true;
mem->writeRawData(*mem->dev().xferQueue(), offset, size, src, WaitForCopy);
return true;
}
void PALHSALoaderContext::GpuMemFree(void *ptr, size_t size)
{
if (program_->isNull()) {
CpuMemFree(ptr, size);
}
else {
delete reinterpret_cast<pal::Memory*>(ptr);
}
}
void* PALHSALoaderContext::KernelCodeAlloc(
size_t size, size_t align, bool zero)
{
address host = CpuMemAlloc(size, align, zero);
pal::Memory* mem = nullptr;
if (!program_->isNull()) {
mem = new pal::Memory(program_->dev(), amd::alignUp(size, align));
if (!mem || !mem->create(pal::Resource::Local)) {
delete mem;
mem = nullptr;
}
}
program_->setCodeObjects(mem, host);
return ((host == nullptr || mem == nullptr) ? nullptr : mem);
}
bool PALHSALoaderContext::KernelCodeCopy(void *dst, size_t offset, const void *src, size_t size)
{
if (!dst || !src || dst == src) {
return false;
}
if (0 == size) {
return true;
}
if (program_->isNull()) {
return CpuMemCopy(dst, offset, src, size);
}
assert(program_->dev().xferQueue());
pal::Memory* mem = reinterpret_cast<pal::Memory*>(dst);
if (mem == &program_->codeSegGpu()) {
return CpuMemCopy(program_->codeSegCpu(), offset, src, size);
}
assert(!"The segement doesn't match code segment in the program!");
return false;
}
void PALHSALoaderContext::KernelCodeFree(void *ptr, size_t size)
{
CpuMemFree(program_->codeSegCpu(), size);
if (!program_->isNull()) {
delete reinterpret_cast<pal::Memory*>(ptr);
}
program_->setCodeObjects(nullptr, nullptr);
}
#if defined(WITH_LIGHTNING_COMPILER)
static hsa_status_t
@@ -34,6 +34,32 @@ namespace pal {
using namespace amd::hsa::loader;
class HSAILProgram;
class Segment : public amd::HeapObject {
public:
Segment();
~Segment();
//! Allocates a segment
bool alloc(HSAILProgram& prog, amdgpu_hsa_elf_segment_t segment,
size_t size, size_t align, bool zero);
//! Copies data from host to the segment
void copy(size_t offset, const void* src, size_t size);
//! Segment freeze
bool freeze(bool destroySysmem);
//! Returns address for GPU access in the segment
uint64_t gpuAddress(size_t offset) const { return gpuAccess_->vmAddress() + offset; }
//! Returns address for CPU access in the segment
void* cpuAddress(size_t offset) const { return cpuAccess_->data() + offset; }
private:
Memory* gpuAccess_; //!< GPU memory for segment access
Memory* cpuAccess_; //!< CPU memory for segment (backing store)
};
class PALHSALoaderContext final: public Context {
public:
PALHSALoaderContext(HSAILProgram* program): program_(program) {}
@@ -93,42 +119,7 @@ public:
hsa_agent_t agent, hsa_ext_sampler_t sampler_handle) override;
private:
void* AgentGlobalAlloc(
hsa_agent_t agent, size_t size, size_t align, bool zero) {
return GpuMemAlloc(size, align, zero);
}
bool AgentGlobalCopy(void *dst, size_t offset, const void *src, size_t size) {
return GpuMemCopy(dst, offset, src, size);
}
void AgentGlobalFree(void *ptr, size_t size) {
GpuMemFree(ptr, size);
}
void* KernelCodeAlloc(size_t size, size_t align, bool zero);
bool KernelCodeCopy(void *dst, size_t offset, const void *src, size_t size);
void KernelCodeFree(void *ptr, size_t size);
address CpuMemAlloc(size_t size, size_t align, bool zero);
bool CpuMemCopy(void *dst, size_t offset, const void* src, size_t size);
void CpuMemFree(void *ptr, size_t size) {
amd::Os::alignedFree(ptr);
}
void* GpuMemAlloc(size_t size, size_t align, bool zero);
bool GpuMemCopy(void *dst, size_t offset, const void *src, size_t size);
void GpuMemFree(void *ptr, size_t size = 0);
PALHSALoaderContext(const PALHSALoaderContext &c);
PALHSALoaderContext& operator=(const PALHSALoaderContext &c);
pal::HSAILProgram* program_;