Kernel *kernel = this->compileKernel(unit, name);
kernel->setSamplerSet(pair.second->getSamplerSet());
kernel->setImageSet(pair.second->getImageSet());
+ kernel->setCompileWorkGroupSize(pair.second->getCompileWorkGroupSize());
kernels.insert(std::make_pair(name, kernel));
}
return true;
OUT_UPDATE_SZ(scratchSize);
OUT_UPDATE_SZ(useSLM);
OUT_UPDATE_SZ(slmSize);
-
+ OUT_UPDATE_SZ(compileWgSize[0]);
+ OUT_UPDATE_SZ(compileWgSize[1]);
+ OUT_UPDATE_SZ(compileWgSize[2]);
/* samplers. */
if (samplerSet) {
has_samplerset = 1;
IN_UPDATE_SZ(scratchSize);
IN_UPDATE_SZ(useSLM);
IN_UPDATE_SZ(slmSize);
+ IN_UPDATE_SZ(compileWgSize[0]);
+ IN_UPDATE_SZ(compileWgSize[1]);
+ IN_UPDATE_SZ(compileWgSize[2]);
IN_UPDATE_SZ(has_samplerset);
if (has_samplerset) {
outs << spaces_nl << " scratchSize: " << scratchSize << "\n";
outs << spaces_nl << " useSLM: " << useSLM << "\n";
outs << spaces_nl << " slmSize: " << slmSize << "\n";
+ outs << spaces_nl << " compileWgSize: " << compileWgSize[0] << compileWgSize[1] << compileWgSize[2] << "\n";
outs << spaces_nl << " Argument Number is " << argNum << "\n";
for (uint32_t i = 0; i < argNum; i++) {
kernel->getSamplerData(samplers);
}
+ static void kernelGetCompileWorkGroupSize(gbe_kernel gbeKernel, size_t wg_size[3]) {
+ if (gbeKernel == NULL) return;
+ const gbe::Kernel *kernel = (const gbe::Kernel*) gbeKernel;
+ kernel->getCompileWorkGroupSize(wg_size);
+ }
+
static size_t kernelGetImageSize(gbe_kernel gbeKernel) {
if (gbeKernel == NULL) return 0;
const gbe::Kernel *kernel = (const gbe::Kernel*) gbeKernel;
GBE_EXPORT_SYMBOL gbe_kernel_get_slm_size_cb *gbe_kernel_get_slm_size = NULL;
GBE_EXPORT_SYMBOL gbe_kernel_get_sampler_size_cb *gbe_kernel_get_sampler_size = NULL;
GBE_EXPORT_SYMBOL gbe_kernel_get_sampler_data_cb *gbe_kernel_get_sampler_data = NULL;
+GBE_EXPORT_SYMBOL gbe_kernel_get_compile_wg_size_cb *gbe_kernel_get_compile_wg_size = NULL;
GBE_EXPORT_SYMBOL gbe_kernel_get_image_size_cb *gbe_kernel_get_image_size = NULL;
GBE_EXPORT_SYMBOL gbe_kernel_get_image_data_cb *gbe_kernel_get_image_data = NULL;
GBE_EXPORT_SYMBOL gbe_set_image_base_index_cb *gbe_set_image_base_index = NULL;
gbe_kernel_get_slm_size = gbe::kernelGetSLMSize;
gbe_kernel_get_sampler_size = gbe::kernelGetSamplerSize;
gbe_kernel_get_sampler_data = gbe::kernelGetSamplerData;
+ gbe_kernel_get_compile_wg_size = gbe::kernelGetCompileWorkGroupSize;
gbe_kernel_get_image_size = gbe::kernelGetImageSize;
gbe_kernel_get_image_data = gbe::kernelGetImageData;
gbe_get_image_base_index = gbe::getImageBaseIndex;
typedef void (gbe_kernel_get_sampler_data_cb)(gbe_kernel gbeKernel, uint32_t *samplers);
extern gbe_kernel_get_sampler_data_cb *gbe_kernel_get_sampler_data;
+/*! Get the content of defined samplers */
+typedef void (gbe_kernel_get_compile_wg_size_cb)(gbe_kernel gbeKernel, size_t wg_sz[3]);
+extern gbe_kernel_get_compile_wg_size_cb *gbe_kernel_get_compile_wg_size;
+
/*! Destroy and deallocate the given program */
typedef void (gbe_program_delete_cb)(gbe_program);
extern gbe_program_delete_cb *gbe_program_delete;
void setImageSet(ir::ImageSet * from) {
imageSet = from;
}
+ /*! Set compile work group size */
+ void setCompileWorkGroupSize(const size_t wg_sz[3]) {
+ compileWgSize[0] = wg_sz[0];
+ compileWgSize[1] = wg_sz[1];
+ compileWgSize[2] = wg_sz[2];
+ }
+ /*! Get compile work group size */
+ void getCompileWorkGroupSize (size_t wg_sz[3]) const {
+ wg_sz[0] = compileWgSize[0];
+ wg_sz[1] = compileWgSize[1];
+ wg_sz[2] = compileWgSize[2];
+ }
/*! Get defined image size */
size_t getImageSize(void) const { return imageSet->getDataSize(); }
/*! Get defined image value array */
Context *ctx; //!< Save context after compiler to alloc constant buffer curbe
ir::SamplerSet *samplerSet;//!< Copy from the corresponding function.
ir::ImageSet *imageSet; //!< Copy from the corresponding function.
+ size_t compileWgSize[3]; //!< required work group size by kernel attribute.
GBE_CLASS(Kernel); //!< Use custom allocators
};
SamplerSet* getSamplerSet(void) const {return samplerSet; }
/*! Get image set in this function */
ImageSet* getImageSet(void) const {return imageSet; }
+ /*! Set required work group size. */
+ void setCompileWorkGroupSize(size_t x, size_t y, size_t z) { compileWgSize[0] = x; compileWgSize[1] = y; compileWgSize[2] = z; }
+ /*! Get required work group size. */
+ const size_t *getCompileWorkGroupSize(void) const {return compileWgSize;}
private:
friend class Context; //!< Can freely modify a function
std::string name; //!< Function name
uint32_t simdWidth; //!< 8 or 16 if forced, 0 otherwise
bool useSLM; //!< Is SLM required?
uint32_t slmSize; //!< local variable size inside kernel function
- SamplerSet *samplerSet; //!< samplers used in this function.
- ImageSet* imageSet; //!< Image set in this function's arguments..
+ SamplerSet *samplerSet; //!< samplers used in this function.
+ ImageSet* imageSet; //!< Image set in this function's arguments..
+ size_t compileWgSize[3]; //!< required work group size specified by
+ // __attribute__((reqd_work_group_size(X, Y, Z))).
GBE_CLASS(Function); //!< Use custom allocator
};
{
GBE_ASSERTM(F.hasStructRetAttr() == false,
"Returned value for kernel functions is forbidden");
+
+ // Loop over the kernel metadatas to set the required work group size.
+ NamedMDNode *clKernelMetaDatas = TheModule->getNamedMetadata("opencl.kernels");
+ size_t reqd_wg_sz[3] = {0, 0, 0};
+ for(uint i = 0; i < clKernelMetaDatas->getNumOperands(); i++)
+ {
+ MDNode *node = clKernelMetaDatas->getOperand(i);
+ if (node->getOperand(0) != &F) continue;
+ for(uint j = 0; j < node->getNumOperands() - 1; j++)
+ {
+ MDNode *attrNode = dyn_cast_or_null<MDNode>(node->getOperand(1 + j));
+ if (attrNode == NULL) break;
+ MDString *attrName = dyn_cast_or_null<MDString>(attrNode->getOperand(0));
+ if (attrName && attrName->getString() == "reqd_work_group_size") {
+ GBE_ASSERT(attrNode->getNumOperands() == 4);
+ ConstantInt *x = dyn_cast<ConstantInt>(attrNode->getOperand(1));
+ ConstantInt *y = dyn_cast<ConstantInt>(attrNode->getOperand(2));
+ ConstantInt *z = dyn_cast<ConstantInt>(attrNode->getOperand(3));
+ GBE_ASSERT(x && y && z);
+ reqd_wg_sz[0] = x->getZExtValue();
+ reqd_wg_sz[1] = y->getZExtValue();
+ reqd_wg_sz[2] = z->getZExtValue();
+ break;
+ }
+ }
+ }
+ ctx.getFunction().setCompileWorkGroupSize(reqd_wg_sz[0], reqd_wg_sz[1], reqd_wg_sz[2]);
// Loop over the arguments and output registers for them
if (!F.arg_empty()) {
uint32_t argID = 0;
goto error;
}
+
/* XXX No event right now */
//FATAL_IF(num_events_in_wait_list > 0, "Events are not supported");
//FATAL_IF(event_wait_list != NULL, "Events are not supported");
for (i = 0; i < work_dim; ++i)
fixed_global_off[i] = global_work_offset[i];
+ if (kernel->compile_wg_sz[0] || kernel->compile_wg_sz[1] || kernel->compile_wg_sz[2]) {
+ if (fixed_local_sz[0] != kernel->compile_wg_sz[0]
+ || fixed_local_sz[1] != kernel->compile_wg_sz[1]
+ || fixed_local_sz[2] != kernel->compile_wg_sz[2])
+ {
+ err = CL_INVALID_WORK_GROUP_SIZE;
+ goto error;
+ }
+ }
+
/* Do device specific checks are enqueue the kernel */
err = cl_command_queue_ND_range(command_queue,
kernel,
.max_work_group_size = 1024,
.max_clock_frequency = 1000,
.wg_sz = 1024,
- .compile_wg_sz = {0},
#include "cl_gen7_device.h"
};
.max_work_group_size = 512,
.max_clock_frequency = 1000,
.wg_sz = 512,
- .compile_wg_sz = {0},
#include "cl_gen7_device.h"
};
.max_work_group_size = 512,
.max_clock_frequency = 1000,
.wg_sz = 512,
- .compile_wg_sz = {0},
#include "cl_gen75_device.h"
};
switch (param_name) {
DECL_FIELD(WORK_GROUP_SIZE, wg_sz)
- DECL_FIELD(COMPILE_WORK_GROUP_SIZE, compile_wg_sz)
DECL_FIELD(PREFERRED_WORK_GROUP_SIZE_MULTIPLE, preferred_wg_sz_mul)
case CL_KERNEL_LOCAL_MEM_SIZE:
if (param_value_size < sizeof(cl_ulong))
*param_value_size_ret = sizeof(cl_ulong);
*(cl_ulong*)param_value = gbe_kernel_get_slm_size(kernel->opaque) + kernel->local_mem_sz;
return CL_SUCCESS;
+ case CL_KERNEL_COMPILE_WORK_GROUP_SIZE:
+ if (param_value_size < sizeof(kernel->compile_wg_sz))
+ return CL_INVALID_VALUE;
+ if (param_value_size_ret != NULL)
+ *param_value_size_ret = sizeof(kernel->compile_wg_sz);
+ memcpy(param_value, kernel->compile_wg_sz, sizeof(kernel->compile_wg_sz));
+ return CL_SUCCESS;
+
default: return CL_INVALID_VALUE;
};
}
size_t built_in_kernels_sz;
/* Kernel specific info that we're assigning statically */
size_t wg_sz;
- size_t compile_wg_sz[3];
size_t preferred_wg_sz_mul;
};
assert(k->sampler_sz <= GEN_MAX_SAMPLERS);
if (k->sampler_sz > 0)
gbe_kernel_get_sampler_data(k->opaque, k->samplers);
+ gbe_kernel_get_compile_wg_size(k->opaque, k->compile_wg_sz);
/* Get image data & size */
k->image_sz = gbe_kernel_get_image_size(k->opaque);
assert(k->sampler_sz <= GEN_MAX_SURFACES);
to->curbe_sz = from->curbe_sz;
to->sampler_sz = from->sampler_sz;
to->image_sz = from->image_sz;
+ memcpy(to->compile_wg_sz, from->compile_wg_sz, sizeof(from->compile_wg_sz));
if (to->sampler_sz)
memcpy(to->samplers, from->samplers, to->sampler_sz * sizeof(uint32_t));
if (to->image_sz) {
struct ImageInfo *images; /* images defined in kernel args */
size_t image_sz; /* image count in kernel args */
cl_ulong local_mem_sz; /* local memory size specified in kernel args. */
+ size_t compile_wg_sz[3]; /* Required workgroup size by __attribute__((reqd_work_gro
+ up_size(X, Y, Z))) qualifier.*/
cl_argument *args; /* To track argument setting */
uint32_t arg_n:31; /* Number of arguments */
uint32_t ref_its_program:1; /* True only for the user kernel (created by clCreateKernel) */