P4 to Git Change 1370387 by wchau@wchau_OCL_boltzmann on 2017/02/07 17:00:35
SWDEV-103424 - [ROCm CQE][OCL] OCLRuntime - OCLCreateBuffer tests are failing. The failure is due to AQL cannot support global size > 32bit range. Adding dispatch split support for ROCm, similar to that of GSL (CL#1159349), to resolve the issue. Affected files ... ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rockernel.hpp#13 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#56 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocvirtual.cpp#31 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocvirtual.hpp#8 edit ... //depot/stg/opencl/drivers/opencl/tests/ocltst/module/runtime/OCLCreateBuffer.cpp#6 edit
Šī revīzija ir iekļauta:
@@ -147,7 +147,21 @@ public:
|
|||||||
//! Return printf info array
|
//! Return printf info array
|
||||||
const std::vector<PrintfInfo>& printfInfo() const {return printf_;}
|
const std::vector<PrintfInfo>& printfInfo() const {return printf_;}
|
||||||
|
|
||||||
|
//! Return TRUE if kernel is internal blit kernel
|
||||||
|
bool isInternalKernel() const { return (flags_.internalKernel_) ? true : false; }
|
||||||
|
|
||||||
|
//! set internal kernel flag
|
||||||
|
void setInternalKernelFlag(bool flag) { flags_.internalKernel_ = flag; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
union Flags {
|
||||||
|
struct {
|
||||||
|
uint internalKernel_: 1; //!< Is a blit kernel?
|
||||||
|
};
|
||||||
|
uint value_;
|
||||||
|
Flags(): value_(0) {}
|
||||||
|
} flags_;
|
||||||
|
|
||||||
//! Populates hsailArgList_
|
//! Populates hsailArgList_
|
||||||
void initArguments(const aclArgData* aclArg);
|
void initArguments(const aclArgData* aclArg);
|
||||||
#if defined(WITH_LIGHTNING_COMPILER)
|
#if defined(WITH_LIGHTNING_COMPILER)
|
||||||
@@ -164,7 +178,6 @@ private:
|
|||||||
|
|
||||||
HSAILProgram *program_; //!< The roc::HSAILProgram context
|
HSAILProgram *program_; //!< The roc::HSAILProgram context
|
||||||
std::vector<Argument*> hsailArgList_; //!< Vector list of HSAIL Arguments
|
std::vector<Argument*> hsailArgList_; //!< Vector list of HSAIL Arguments
|
||||||
std::string compileOptions_; //!< compile used for finalizing this kernel
|
|
||||||
uint64_t kernelCodeHandle_; //!< Kernel code handle (aka amd_kernel_code_t)
|
uint64_t kernelCodeHandle_; //!< Kernel code handle (aka amd_kernel_code_t)
|
||||||
const uint32_t workgroupGroupSegmentByteSize_;
|
const uint32_t workgroupGroupSegmentByteSize_;
|
||||||
const uint32_t workitemPrivateSegmentByteSize_;
|
const uint32_t workitemPrivateSegmentByteSize_;
|
||||||
|
|||||||
@@ -1080,6 +1080,7 @@ HSAILProgram::setKernels_LC(amd::option::Options *options, void* binary, size_t
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize);
|
aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize);
|
||||||
|
aKernel->setInternalKernelFlag(compileOptions_.find("-cl-internal-kernel") != std::string::npos);
|
||||||
kernels()[kernelName] = aKernel;
|
kernels()[kernelName] = aKernel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1336,6 +1337,7 @@ HSAILProgram::linkImpl(amd::option::Options *options)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize);
|
aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize);
|
||||||
|
aKernel->setInternalKernelFlag(compileOptions_.find("-cl-internal-kernel") != std::string::npos);
|
||||||
kernels()[kernelName] = aKernel;
|
kernels()[kernelName] = aKernel;
|
||||||
}
|
}
|
||||||
saveBinaryAndSetType(TYPE_EXECUTABLE);
|
saveBinaryAndSetType(TYPE_EXECUTABLE);
|
||||||
|
|||||||
@@ -1513,210 +1513,257 @@ VirtualGPU::submitKernelInternal(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate buffer to hold kernel arguments
|
|
||||||
address argBuffer = (address)allocKernArg(
|
|
||||||
gpuKernel.KernargSegmentByteSize(),
|
|
||||||
gpuKernel.KernargSegmentAlignment());
|
|
||||||
|
|
||||||
if (argBuffer == NULL) {
|
|
||||||
LogError("Out of memory");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
address argPtr = argBuffer;
|
|
||||||
const amd::KernelSignature& signature = kernel.signature();
|
const amd::KernelSignature& signature = kernel.signature();
|
||||||
const amd::KernelParameters& kernelParams = kernel.parameters();
|
const amd::KernelParameters& kernelParams = kernel.parameters();
|
||||||
|
|
||||||
// Find all parameters for the current kernel
|
size_t newOffset[3] = {0, 0, 0};
|
||||||
for (auto arg : gpuKernel.hsailArgs()) {
|
size_t newGlobalSize[3] = {0, 0, 0};
|
||||||
const_address srcArgPtr = NULL;
|
|
||||||
if (arg->index_ != uint(-1)) {
|
|
||||||
srcArgPtr = parameters + signature.at(arg->index_).offset_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the hidden arguments first, as they do not have a
|
int dim = -1;
|
||||||
// matching parameter in the OCL signature (not a valid arg->index_)
|
int iteration = 1;
|
||||||
switch (arg->type_) {
|
size_t globalStep = 0;
|
||||||
case ROC_ARGTYPE_HIDDEN_GLOBAL_OFFSET_X: {
|
for (uint i = 0; i < sizes.dimensions(); i++) {
|
||||||
size_t offset_x = sizes.dimensions() >= 1 ? sizes.offset()[0] : 0;
|
newGlobalSize[i] = sizes.global()[i];
|
||||||
assert(arg->size_ == sizeof(offset_x) && "check the sizes");
|
newOffset[i] = sizes.offset()[i];
|
||||||
argPtr = addArg(argPtr, &offset_x, arg->size_, arg->alignment_);
|
}
|
||||||
break;
|
|
||||||
}
|
if (gpuKernel.isInternalKernel()) {
|
||||||
case ROC_ARGTYPE_HIDDEN_GLOBAL_OFFSET_Y: {
|
// Calculate new group size for each submission
|
||||||
size_t offset_y = sizes.dimensions() >= 2 ? sizes.offset()[1] : 0;
|
for (uint i = 0; i < sizes.dimensions(); i++) {
|
||||||
assert(arg->size_ == sizeof(offset_y) && "check the sizes");
|
if (sizes.global()[i] > static_cast<size_t>(0xffffffff)) {
|
||||||
argPtr = addArg(argPtr, &offset_y, arg->size_, arg->alignment_);
|
dim = i;
|
||||||
break;
|
iteration = sizes.global()[i] / 0xC0000000
|
||||||
}
|
+ ((sizes.global()[i] % 0xC0000000) ? 1: 0);
|
||||||
case ROC_ARGTYPE_HIDDEN_GLOBAL_OFFSET_Z: {
|
globalStep = (sizes.global()[i] / sizes.local()[i]) / iteration
|
||||||
size_t offset_z = sizes.dimensions() == 3 ? sizes.offset()[2] : 0;
|
* sizes.local()[dim];
|
||||||
assert(arg->size_ == sizeof(offset_z) && "check the sizes");
|
if (timestamp_ != nullptr) {
|
||||||
argPtr = addArg(argPtr, &offset_z, arg->size_, arg->alignment_);
|
timestamp_->setSplittedDispatch();
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
case ROC_ARGTYPE_HIDDEN_PRINTF_BUFFER: {
|
|
||||||
address bufferPtr = printfDbg()->dbgBuffer();
|
|
||||||
assert(arg->size_ == sizeof(bufferPtr) && "check the sizes");
|
|
||||||
argPtr = addArg(argPtr, &bufferPtr, arg->size_, arg->alignment_);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ROC_ARGTYPE_HIDDEN_DEFAULT_QUEUE:
|
|
||||||
case ROC_ARGTYPE_HIDDEN_COMPLETION_ACTION:
|
|
||||||
case ROC_ARGTYPE_HIDDEN_NONE: {
|
|
||||||
void* zero = 0;
|
|
||||||
assert(arg->size_ <= sizeof(zero) && "check the sizes");
|
|
||||||
argPtr = addArg(argPtr, &zero, arg->size_, arg->alignment_);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ROC_ARGTYPE_POINTER: {
|
|
||||||
if (arg->addrQual_ == ROC_ADDRESS_LOCAL) {
|
|
||||||
// Align the LDS on the alignment requirement of type pointed to
|
|
||||||
ldsUsage = amd::alignUp(ldsUsage, arg->pointeeAlignment_);
|
|
||||||
argPtr = addArg(argPtr, &ldsUsage, arg->size_, arg->alignment_);
|
|
||||||
ldsUsage += *reinterpret_cast<const size_t *>(srcArgPtr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert((arg->addrQual_ == ROC_ADDRESS_GLOBAL
|
|
||||||
|| arg->addrQual_ == ROC_ADDRESS_CONSTANT)
|
|
||||||
&& "Unsupported address qualifier");
|
|
||||||
if (kernelParams.boundToSvmPointer(dev(), parameters, arg->index_)) {
|
|
||||||
argPtr = addArg(argPtr, srcArgPtr, arg->size_, arg->alignment_);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
amd::Memory* mem = *reinterpret_cast<amd::Memory* const*>(srcArgPtr);
|
|
||||||
if (mem == NULL) {
|
|
||||||
argPtr = addArg(argPtr, srcArgPtr, arg->size_, arg->alignment_);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory *devMem = static_cast<Memory *>(mem->getDeviceMemory(dev()));
|
|
||||||
//! @todo add multi-devices synchronization when supported.
|
|
||||||
void* globalAddress = devMem->getDeviceMemory();
|
|
||||||
argPtr = addArg(argPtr, &globalAddress, arg->size_, arg->alignment_);
|
|
||||||
|
|
||||||
//! @todo Compiler has to return read/write attributes
|
|
||||||
const cl_mem_flags flags = mem->getMemFlags();
|
|
||||||
if (!flags || (flags & (CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY))) {
|
|
||||||
mem->signalWrite(&dev());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ROC_ARGTYPE_REFERENCE: {
|
}
|
||||||
void *mem = allocKernArg(arg->size_, arg->alignment_);
|
|
||||||
if (mem == NULL) {
|
|
||||||
LogError("Out of memory");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(mem, srcArgPtr, arg->size_);
|
|
||||||
argPtr = addArg(argPtr, &mem, sizeof(void*));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ROC_ARGTYPE_VALUE:
|
|
||||||
argPtr = addArg(argPtr, srcArgPtr, arg->size_, arg->alignment_);
|
|
||||||
break;
|
|
||||||
case ROC_ARGTYPE_IMAGE: {
|
|
||||||
amd::Memory* mem = *reinterpret_cast<amd::Memory* const*>(srcArgPtr);
|
|
||||||
Image* image = static_cast<Image *>(mem->getDeviceMemory(dev()));
|
|
||||||
if (image == NULL) {
|
|
||||||
LogError("Kernel image argument is not an image object");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev().settings().enableImageHandle_) {
|
for (int j = 0; j < iteration; j++) {
|
||||||
const uint64_t image_srd = image->getHsaImageObject().handle;
|
// Reset global size for dimension dim if split is needed
|
||||||
assert(amd::isMultipleOf(image_srd, sizeof(image_srd)));
|
if (dim != -1) {
|
||||||
argPtr = addArg(argPtr, &image_srd, sizeof(image_srd));
|
newOffset[dim] = sizes.offset()[dim] + globalStep * j;
|
||||||
|
if (((newOffset[dim] + globalStep) < sizes.global()[dim]) &&
|
||||||
|
(j != (iteration - 1))) {
|
||||||
|
newGlobalSize[dim] = globalStep;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Image arguments are of size 48 bytes and are aligned to 16 bytes
|
newGlobalSize[dim] = sizes.global()[dim] - newOffset[dim];
|
||||||
argPtr = addArg(argPtr, (void *)image->getHsaImageObject().handle,
|
|
||||||
HSA_IMAGE_OBJECT_SIZE, HSA_IMAGE_OBJECT_ALIGNMENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! @todo Compiler has to return read/write attributes
|
|
||||||
const cl_mem_flags flags = mem->getMemFlags();
|
|
||||||
if (!flags || (flags & (CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY))) {
|
|
||||||
mem->signalWrite(&dev());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ROC_ARGTYPE_SAMPLER: {
|
|
||||||
amd::Sampler* sampler = *reinterpret_cast<amd::Sampler* const*>(srcArgPtr);
|
|
||||||
if (sampler == NULL) {
|
|
||||||
LogError("Kernel sampler argument is not an sampler object");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hsa_ext_sampler_descriptor_t samplerDescriptor;
|
// Find all parameters for the current kernel
|
||||||
fillSampleDescriptor(samplerDescriptor, *sampler);
|
|
||||||
|
|
||||||
hsa_ext_sampler_t hsa_sampler;
|
// Allocate buffer to hold kernel arguments
|
||||||
hsa_status_t status = hsa_ext_sampler_create(dev().getBackendDevice(),
|
address argBuffer = (address)allocKernArg(
|
||||||
&samplerDescriptor, &hsa_sampler);
|
gpuKernel.KernargSegmentByteSize(),
|
||||||
if (status != HSA_STATUS_SUCCESS) {
|
gpuKernel.KernargSegmentAlignment());
|
||||||
LogError("Error creating device sampler object!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev().settings().enableImageHandle_) {
|
if (argBuffer == NULL) {
|
||||||
uint64_t sampler_srd = hsa_sampler.handle;
|
LogError("Out of memory");
|
||||||
argPtr = addArg(argPtr, &sampler_srd, sizeof(sampler_srd));
|
|
||||||
samplerList_.push_back(hsa_sampler);
|
|
||||||
// TODO: destroy sampler.
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
argPtr = amd::alignUp(argPtr, HSA_SAMPLER_OBJECT_ALIGNMENT);
|
|
||||||
|
|
||||||
memcpy(argPtr, (void*)hsa_sampler.handle, HSA_SAMPLER_OBJECT_SIZE);
|
|
||||||
argPtr += HSA_SAMPLER_OBJECT_SIZE;
|
|
||||||
hsa_ext_sampler_destroy(dev().getBackendDevice(), hsa_sampler);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check there is no arguments' buffer overflow
|
address argPtr = argBuffer;
|
||||||
assert(argPtr <= argBuffer + gpuKernel.KernargSegmentByteSize());
|
for (auto arg : gpuKernel.hsailArgs()) {
|
||||||
|
const_address srcArgPtr = NULL;
|
||||||
|
if (arg->index_ != uint(-1)) {
|
||||||
|
srcArgPtr = parameters + signature.at(arg->index_).offset_;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for group memory overflow
|
// Handle the hidden arguments first, as they do not have a
|
||||||
//! @todo Check should be in HSA - here we should have at most an assert
|
// matching parameter in the OCL signature (not a valid arg->index_)
|
||||||
assert(roc_device_.info().localMemSizePerCU_ > 0);
|
switch (arg->type_) {
|
||||||
if (ldsUsage > roc_device_.info().localMemSizePerCU_) {
|
case ROC_ARGTYPE_HIDDEN_GLOBAL_OFFSET_X: {
|
||||||
LogError("No local memory available\n");
|
size_t offset_x = sizes.dimensions() >= 1 ? newOffset[0] : 0;
|
||||||
return false;
|
assert(arg->size_ == sizeof(offset_x) && "check the sizes");
|
||||||
}
|
argPtr = addArg(argPtr, &offset_x, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_HIDDEN_GLOBAL_OFFSET_Y: {
|
||||||
|
size_t offset_y = sizes.dimensions() >= 2 ? newOffset[1] : 0;
|
||||||
|
assert(arg->size_ == sizeof(offset_y) && "check the sizes");
|
||||||
|
argPtr = addArg(argPtr, &offset_y, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_HIDDEN_GLOBAL_OFFSET_Z: {
|
||||||
|
size_t offset_z = sizes.dimensions() == 3 ? newOffset[2] : 0;
|
||||||
|
assert(arg->size_ == sizeof(offset_z) && "check the sizes");
|
||||||
|
argPtr = addArg(argPtr, &offset_z, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_HIDDEN_PRINTF_BUFFER: {
|
||||||
|
address bufferPtr = printfDbg()->dbgBuffer();
|
||||||
|
assert(arg->size_ == sizeof(bufferPtr) && "check the sizes");
|
||||||
|
argPtr = addArg(argPtr, &bufferPtr, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_HIDDEN_DEFAULT_QUEUE:
|
||||||
|
case ROC_ARGTYPE_HIDDEN_COMPLETION_ACTION:
|
||||||
|
case ROC_ARGTYPE_HIDDEN_NONE: {
|
||||||
|
void* zero = 0;
|
||||||
|
assert(arg->size_ <= sizeof(zero) && "check the sizes");
|
||||||
|
argPtr = addArg(argPtr, &zero, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_POINTER: {
|
||||||
|
if (arg->addrQual_ == ROC_ADDRESS_LOCAL) {
|
||||||
|
// Align the LDS on the alignment requirement of type pointed to
|
||||||
|
ldsUsage = amd::alignUp(ldsUsage, arg->pointeeAlignment_);
|
||||||
|
argPtr = addArg(argPtr, &ldsUsage, arg->size_, arg->alignment_);
|
||||||
|
ldsUsage += *reinterpret_cast<const size_t *>(srcArgPtr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert((arg->addrQual_ == ROC_ADDRESS_GLOBAL
|
||||||
|
|| arg->addrQual_ == ROC_ADDRESS_CONSTANT)
|
||||||
|
&& "Unsupported address qualifier");
|
||||||
|
if (kernelParams.boundToSvmPointer(dev(), parameters, arg->index_)) {
|
||||||
|
argPtr = addArg(argPtr, srcArgPtr, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
amd::Memory* mem = *reinterpret_cast<amd::Memory* const*>(srcArgPtr);
|
||||||
|
if (mem == NULL) {
|
||||||
|
argPtr = addArg(argPtr, srcArgPtr, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//Initialize the dispatch Packet
|
Memory *devMem = static_cast<Memory *>(mem->getDeviceMemory(dev()));
|
||||||
hsa_kernel_dispatch_packet_t dispatchPacket;
|
//! @todo add multi-devices synchronization when supported.
|
||||||
memset(&dispatchPacket, 0, sizeof(dispatchPacket));
|
void* globalAddress = devMem->getDeviceMemory();
|
||||||
|
argPtr = addArg(argPtr, &globalAddress, arg->size_, arg->alignment_);
|
||||||
|
|
||||||
dispatchPacket.kernel_object = gpuKernel.KernelCodeHandle();
|
//! @todo Compiler has to return read/write attributes
|
||||||
|
const cl_mem_flags flags = mem->getMemFlags();
|
||||||
|
if (!flags || (flags & (CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY))) {
|
||||||
|
mem->signalWrite(&dev());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_REFERENCE: {
|
||||||
|
void *mem = allocKernArg(arg->size_, arg->alignment_);
|
||||||
|
if (mem == NULL) {
|
||||||
|
LogError("Out of memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(mem, srcArgPtr, arg->size_);
|
||||||
|
argPtr = addArg(argPtr, &mem, sizeof(void*));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROC_ARGTYPE_VALUE:
|
||||||
|
argPtr = addArg(argPtr, srcArgPtr, arg->size_, arg->alignment_);
|
||||||
|
break;
|
||||||
|
case ROC_ARGTYPE_IMAGE: {
|
||||||
|
amd::Memory* mem = *reinterpret_cast<amd::Memory* const*>(srcArgPtr);
|
||||||
|
Image* image = static_cast<Image *>(mem->getDeviceMemory(dev()));
|
||||||
|
if (image == NULL) {
|
||||||
|
LogError("Kernel image argument is not an image object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
dispatchPacket.header = aqlHeader_;
|
if (dev().settings().enableImageHandle_) {
|
||||||
dispatchPacket.setup |= sizes.dimensions() << HSA_KERNEL_DISPATCH_PACKET_SETUP_DIMENSIONS;
|
const uint64_t image_srd = image->getHsaImageObject().handle;
|
||||||
dispatchPacket.grid_size_x = sizes.dimensions()>0 ? sizes.global()[0] : 1;
|
assert(amd::isMultipleOf(image_srd, sizeof(image_srd)));
|
||||||
dispatchPacket.grid_size_y = sizes.dimensions()>1 ? sizes.global()[1] : 1;
|
argPtr = addArg(argPtr, &image_srd, sizeof(image_srd));
|
||||||
dispatchPacket.grid_size_z = sizes.dimensions()>2 ? sizes.global()[2] : 1;
|
}
|
||||||
|
else {
|
||||||
|
// Image arguments are of size 48 bytes and are aligned to 16 bytes
|
||||||
|
argPtr = addArg(argPtr, (void *)image->getHsaImageObject().handle,
|
||||||
|
HSA_IMAGE_OBJECT_SIZE, HSA_IMAGE_OBJECT_ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t* compile_size = devKernel->workGroupInfo()->compileSize_;
|
//! @todo Compiler has to return read/write attributes
|
||||||
if (sizes.local().product() != 0) {
|
const cl_mem_flags flags = mem->getMemFlags();
|
||||||
dispatchPacket.workgroup_size_x = sizes.dimensions()>0 ? sizes.local()[0] : 1;
|
if (!flags || (flags & (CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY))) {
|
||||||
dispatchPacket.workgroup_size_y = sizes.dimensions()>1 ? sizes.local()[1] : 1;
|
mem->signalWrite(&dev());
|
||||||
dispatchPacket.workgroup_size_z = sizes.dimensions()>2 ? sizes.local()[2] : 1;
|
}
|
||||||
} else {
|
break;
|
||||||
setRuntimeCompilerLocalSize(dispatchPacket, sizes, compile_size, dev());
|
}
|
||||||
}
|
case ROC_ARGTYPE_SAMPLER: {
|
||||||
dispatchPacket.kernarg_address = argBuffer;
|
amd::Sampler* sampler = *reinterpret_cast<amd::Sampler* const*>(srcArgPtr);
|
||||||
dispatchPacket.group_segment_size = ldsUsage;
|
if (sampler == NULL) {
|
||||||
dispatchPacket.private_segment_size = devKernel->workGroupInfo()->privateMemSize_;
|
LogError("Kernel sampler argument is not an sampler object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//Dispatch the packet
|
hsa_ext_sampler_descriptor_t samplerDescriptor;
|
||||||
if (!dispatchAqlPacket(&dispatchPacket, GPU_FLUSH_ON_EXECUTION)){
|
fillSampleDescriptor(samplerDescriptor, *sampler);
|
||||||
return false;
|
|
||||||
|
hsa_ext_sampler_t hsa_sampler;
|
||||||
|
hsa_status_t status = hsa_ext_sampler_create(dev().getBackendDevice(),
|
||||||
|
&samplerDescriptor, &hsa_sampler);
|
||||||
|
if (status != HSA_STATUS_SUCCESS) {
|
||||||
|
LogError("Error creating device sampler object!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev().settings().enableImageHandle_) {
|
||||||
|
uint64_t sampler_srd = hsa_sampler.handle;
|
||||||
|
argPtr = addArg(argPtr, &sampler_srd, sizeof(sampler_srd));
|
||||||
|
samplerList_.push_back(hsa_sampler);
|
||||||
|
// TODO: destroy sampler.
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
argPtr = amd::alignUp(argPtr, HSA_SAMPLER_OBJECT_ALIGNMENT);
|
||||||
|
|
||||||
|
memcpy(argPtr, (void*)hsa_sampler.handle, HSA_SAMPLER_OBJECT_SIZE);
|
||||||
|
argPtr += HSA_SAMPLER_OBJECT_SIZE;
|
||||||
|
hsa_ext_sampler_destroy(dev().getBackendDevice(), hsa_sampler);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check there is no arguments' buffer overflow
|
||||||
|
assert(argPtr <= argBuffer + gpuKernel.KernargSegmentByteSize());
|
||||||
|
|
||||||
|
// Check for group memory overflow
|
||||||
|
//! @todo Check should be in HSA - here we should have at most an assert
|
||||||
|
assert(roc_device_.info().localMemSizePerCU_ > 0);
|
||||||
|
if (ldsUsage > roc_device_.info().localMemSizePerCU_) {
|
||||||
|
LogError("No local memory available\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize the dispatch Packet
|
||||||
|
hsa_kernel_dispatch_packet_t dispatchPacket;
|
||||||
|
memset(&dispatchPacket, 0, sizeof(dispatchPacket));
|
||||||
|
|
||||||
|
dispatchPacket.kernel_object = gpuKernel.KernelCodeHandle();
|
||||||
|
|
||||||
|
dispatchPacket.header = aqlHeader_;
|
||||||
|
dispatchPacket.setup |= sizes.dimensions() << HSA_KERNEL_DISPATCH_PACKET_SETUP_DIMENSIONS;
|
||||||
|
dispatchPacket.grid_size_x = sizes.dimensions()>0 ? newGlobalSize[0] : 1;
|
||||||
|
dispatchPacket.grid_size_y = sizes.dimensions()>1 ? newGlobalSize[1] : 1;
|
||||||
|
dispatchPacket.grid_size_z = sizes.dimensions()>2 ? newGlobalSize[2] : 1;
|
||||||
|
|
||||||
|
const size_t* compile_size = devKernel->workGroupInfo()->compileSize_;
|
||||||
|
if (sizes.local().product() != 0) {
|
||||||
|
dispatchPacket.workgroup_size_x = sizes.dimensions()>0 ? sizes.local()[0] : 1;
|
||||||
|
dispatchPacket.workgroup_size_y = sizes.dimensions()>1 ? sizes.local()[1] : 1;
|
||||||
|
dispatchPacket.workgroup_size_z = sizes.dimensions()>2 ? sizes.local()[2] : 1;
|
||||||
|
} else {
|
||||||
|
amd::NDRangeContainer tmpSizes(sizes.dimensions(),
|
||||||
|
&newOffset[0], &newGlobalSize[0],
|
||||||
|
&(const_cast<amd::NDRangeContainer&>(sizes).local()[0]));
|
||||||
|
|
||||||
|
setRuntimeCompilerLocalSize(dispatchPacket, tmpSizes, compile_size, dev());
|
||||||
|
}
|
||||||
|
dispatchPacket.kernarg_address = argBuffer;
|
||||||
|
dispatchPacket.group_segment_size = ldsUsage;
|
||||||
|
dispatchPacket.private_segment_size = devKernel->workGroupInfo()->privateMemSize_;
|
||||||
|
|
||||||
|
//Dispatch the packet
|
||||||
|
if (!dispatchAqlPacket(&dispatchPacket, GPU_FLUSH_ON_EXECUTION)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the flag indicating if a dispatch is outstanding.
|
// Mark the flag indicating if a dispatch is outstanding.
|
||||||
|
|||||||
@@ -29,53 +29,80 @@ struct ProfilingSignal : public amd::HeapObject
|
|||||||
// including EnqueueNDRangeKernel and clEnqueueCopyBuffer.
|
// including EnqueueNDRangeKernel and clEnqueueCopyBuffer.
|
||||||
class Timestamp {
|
class Timestamp {
|
||||||
private:
|
private:
|
||||||
uint64_t start_;
|
uint64_t start_;
|
||||||
uint64_t end_;
|
uint64_t end_;
|
||||||
ProfilingSignal* profilingSignal_;
|
ProfilingSignal* profilingSignal_;
|
||||||
hsa_agent_t agent_;
|
hsa_agent_t agent_;
|
||||||
static double ticksToTime_;
|
static double ticksToTime_;
|
||||||
|
bool splittedDispatch_;
|
||||||
|
std::vector<hsa_signal_t> splittedSignals_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint64_t getStart() { checkGpuTime(); return start_; }
|
uint64_t getStart() { checkGpuTime(); return start_; }
|
||||||
|
|
||||||
uint64_t getEnd() { checkGpuTime(); return end_; }
|
uint64_t getEnd() { checkGpuTime(); return end_; }
|
||||||
|
|
||||||
void setProfilingSignal(ProfilingSignal* signal) { profilingSignal_ = signal; }
|
void setProfilingSignal(ProfilingSignal* signal) {
|
||||||
|
profilingSignal_ = signal;
|
||||||
|
if (splittedDispatch_) {
|
||||||
|
splittedSignals_.push_back(profilingSignal_->signal_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ProfilingSignal* getProfilingSignal() const { return profilingSignal_; }
|
||||||
|
|
||||||
const ProfilingSignal* getProfilingSignal() const { return profilingSignal_; }
|
void setAgent(hsa_agent_t agent) { agent_ = agent; }
|
||||||
|
|
||||||
void setAgent(hsa_agent_t agent) { agent_ = agent; }
|
Timestamp() : start_(0), end_(0), profilingSignal_(nullptr), splittedDispatch_(false) {
|
||||||
|
agent_.handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Timestamp() : start_(0), end_(0), profilingSignal_(nullptr) {
|
~Timestamp() {}
|
||||||
agent_.handle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Timestamp() {}
|
//! Finds execution ticks on GPU
|
||||||
|
void checkGpuTime() {
|
||||||
|
if (profilingSignal_ != nullptr) {
|
||||||
|
hsa_amd_profiling_dispatch_time_t time;
|
||||||
|
|
||||||
//! Finds execution ticks on GPU
|
if (splittedDispatch_) {
|
||||||
void checkGpuTime() {
|
uint64_t start = UINT64_MAX;
|
||||||
if (profilingSignal_ != nullptr) {
|
uint64_t end = 0;
|
||||||
hsa_amd_profiling_dispatch_time_t time;
|
for (auto it = splittedSignals_.begin(); it < splittedSignals_.end(); it++) {
|
||||||
hsa_amd_profiling_get_dispatch_time(agent_, profilingSignal_->signal_, &time);
|
hsa_amd_profiling_get_dispatch_time(agent_, *it, &time);
|
||||||
start_ = time.start * ticksToTime_;
|
if (time.start < start) {
|
||||||
end_ = time.end * ticksToTime_;
|
start = time.start;
|
||||||
profilingSignal_->ts_ = nullptr;
|
}
|
||||||
profilingSignal_ = nullptr;
|
if (time.end > end) {
|
||||||
}
|
end = time.end;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
start_ = start * ticksToTime_;
|
||||||
|
end_ = end * ticksToTime_;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hsa_amd_profiling_get_dispatch_time(agent_, profilingSignal_->signal_, &time);
|
||||||
|
start_ = time.start * ticksToTime_;
|
||||||
|
end_ = time.end * ticksToTime_;
|
||||||
|
}
|
||||||
|
profilingSignal_->ts_ = nullptr;
|
||||||
|
profilingSignal_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start a timestamp (get timestamp from OS)
|
// Start a timestamp (get timestamp from OS)
|
||||||
void start() {
|
void start() {
|
||||||
start_ = amd::Os::timeNanos();
|
start_ = amd::Os::timeNanos();
|
||||||
}
|
}
|
||||||
|
|
||||||
// End a timestamp (get timestamp from OS)
|
// End a timestamp (get timestamp from OS)
|
||||||
void end() {
|
void end() {
|
||||||
end_ = amd::Os::timeNanos();
|
end_ = amd::Os::timeNanos();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setGpuTicksToTime(double ticksToTime) { ticksToTime_=ticksToTime; }
|
bool isSplittedDispatch() const { return splittedDispatch_; }
|
||||||
static double getGpuTicksToTime() { return ticksToTime_; }
|
void setSplittedDispatch() { splittedDispatch_ = true; }
|
||||||
|
|
||||||
|
static void setGpuTicksToTime(double ticksToTime) { ticksToTime_=ticksToTime; }
|
||||||
|
static double getGpuTicksToTime() { return ticksToTime_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class VirtualGPU : public device::VirtualDevice {
|
class VirtualGPU : public device::VirtualDevice {
|
||||||
|
|||||||
Atsaukties uz šo jaunā problēmā
Block a user