#include "clKernelClass.h"

//--------------------------------------------------------
//----------          clKernelClass           ------------
//--------------------------------------------------------
// -------------------------------------------------------

// -------------------------------------------------------
//! \brief  プライベートメンバの初期値を入れる.
//! \param  なし.
//! \return なし.
clKernelClass::clKernelClass()
{
    __CONSTRUCTOR;
}

// -------------------------------------------------------
//! \brief  プライベートメンバの初期値を入れる.
//! \param  program OpenCLのプログラムオブジェクト.
//! \return カーネル(デバイス実行する関数)の名前.
clKernelClass::clKernelClass(cl_program program, std::string kernel_name)
{try{
	
	createKernel(program, kernel_name);
}
catch(clErrorClass &err){err.showErrMsg();}catch(...){std::cerr << "fatal error." << std::endl;}}

// -------------------------------------------------------
//! \brief  特に何もしない.
//! \param  なし.
//! \return なし.
clKernelClass::~clKernelClass(void)
{
    __DESTRUCTOR;
	for(unsigned int i=0; i<kernel.size(); ++i){
	    clReleaseKernel(kernel[i]);
	}
}

// -------------------------------------------------------
//! \brief  カーネルを作成する.
//! \param  なし.
//! \return なし.
const void clKernelClass::createKernel(cl_program program,  
	                                   std::string kernel_name) throw(clErrorClass)
{
    cl_int status;
    this->kernel_name.push_back(kernel_name);
	this->kernel.push_back(
		clCreateKernel(program,
                       kernel_name.c_str(), 
                       &status));
    if(status != CL_SUCCESS){
        throw clErrorClass(status, "clCreateKernel failed.", __FUNCTION__);
    }
}

// -------------------------------------------------------
//! \brief  カーネルを取得.
//! \param  カーネルの名前.
//! \return カーネルを返却する.
const cl_kernel clKernelClass::getKernel(std::string string)
{
    return kernel[getKernelIndex(string)];
}

// -------------------------------------------------------
//! \brief  カーネルの参照を取得.
//! \param  カーネルの名前.
//! \return カーネルの参照を返却する.
const unsigned int clKernelClass::getKernelIndex(std::string name)
{
    unsigned int index=0;
    for(index=0; index<kernel_name.size(); ++index){
        if(kernel_name[index] == name){
            goto LOOP_SUCCESS;
        }
    }
    index = 0;
    std::cerr << __FUNCTION__  << std::endl <<  "Invalied value."<< std::endl;
LOOP_SUCCESS:
    return index;
}








#if 1

// -------------------------------------------------------
//! \brief  カーネルの参照を取得.
//! \param  カーネルの名前.
//! \return カーネルの参照を返却する.
void clKernelClass::setKernelArgs(std::string  kernel_name,
	                             cl_mem       *memory,
								 unsigned int arg_index,
								 size_t       memory_size
								 )
{try{
	cl_uint status;
    status = clSetKernelArg(kernel[getKernelIndex(kernel_name)],
                            arg_index,
                            memory_size,
				            memory);
	if(status != CL_SUCCESS){
		throw clErrorClass(status, "set kernel arguments failed.", __FUNCTION__);
	}
}
catch(clErrorClass &err){err.showErrMsg();}catch(...){std::cerr << "unknown error." << std::endl;}}

// -------------------------------------------------------
//! \brief  カーネルの参照を取得.
//! \param  カーネルの名前.
//! \return カーネルの参照を返却する.
void clKernelClass::setKernelArgs(std::string kernel_name,
	                             void            *memory,
								 unsigned int arg_index,
								 size_t       memory_size)
{try{
	cl_uint status;
    status = clSetKernelArg(kernel[getKernelIndex(kernel_name)],
                            arg_index,
                            sizeof(memory),
				            memory);
	if(status != CL_SUCCESS){
		throw clErrorClass(status, "set kernel arguments failed.", __FUNCTION__);
	}
}
catch(clErrorClass &err){err.showErrMsg();}catch(...){std::cerr << "unknown error." << std::endl;}}

#endif