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]
Αυτή η υποβολή περιλαμβάνεται σε:
@@ -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_;
|
||||
|
||||
Αναφορά σε νέο ζήτημα
Block a user