static void create_clobj(size_t kpc, struct fmt_main *self)
{
	host_pass = mem_calloc(kpc, sizeof(pass_t));
	host_crack = mem_calloc(kpc, sizeof(crack_t));
	host_salt = mem_calloc(1, sizeof(salt_t));
#define CL_RO CL_MEM_READ_ONLY
#define CL_WO CL_MEM_WRITE_ONLY
#define CL_RW CL_MEM_READ_WRITE

#define CLCREATEBUFFER(_flags, _size, _string)	  \
	clCreateBuffer(context[gpu_id], _flags, _size, NULL, &cl_error); \
	HANDLE_CLERROR(cl_error, _string);

#define CLKERNELARG(kernel, id, arg, msg)	  \
	HANDLE_CLERROR(clSetKernelArg(kernel, id, sizeof(arg), &arg), msg);

	mem_in = CLCREATEBUFFER(CL_RO, kpc * sizeof(pass_t),
	                        "Cannot allocate mem in");
	mem_salt = CLCREATEBUFFER(CL_RO, sizeof(salt_t),
	                          "Cannot allocate mem salt");
	mem_out = CLCREATEBUFFER(CL_WO, kpc * sizeof(crack_t),
	                         "Cannot allocate mem out");
	mem_state = CLCREATEBUFFER(CL_RW, kpc * sizeof(state_t),
	                           "Cannot allocate mem state");

	CLKERNELARG(crypt_kernel, 0, mem_in, "Error while setting mem_in");
	CLKERNELARG(crypt_kernel, 1, mem_salt, "Error while setting mem_salt");
	CLKERNELARG(crypt_kernel, 2, mem_state, "Error while setting mem_state");

	CLKERNELARG(split_kernel, 0, mem_state, "Error while setting mem_state");
	CLKERNELARG(split_kernel, 1 ,mem_out, "Error while setting mem_out");
}
static void create_clobj(int kpc, struct fmt_main *self)
{

	host_pass = mem_calloc(kpc * sizeof(pass_t));
	host_crack = mem_calloc(kpc * sizeof(crack_t));
	host_salt = mem_calloc(sizeof(salt_t));
#define CL_RO CL_MEM_READ_ONLY
#define CL_WO CL_MEM_WRITE_ONLY

#define CLCREATEBUFFER(_flags, _size, _string)\
	clCreateBuffer(context[ocl_gpu_id], _flags, _size, NULL, &cl_error);\
	HANDLE_CLERROR(cl_error, _string);

	mem_in =
	    CLCREATEBUFFER(CL_RO, kpc * sizeof(pass_t),
	    "Cannot allocate mem in");
	mem_salt =
	    CLCREATEBUFFER(CL_RO, sizeof(salt_t), "Cannot allocate mem salt");
	mem_out =
	    CLCREATEBUFFER(CL_WO, kpc * sizeof(crack_t),
	    "Cannot allocate mem out");

	HANDLE_CLERROR(clSetKernelArg(crypt_kernel, 0, sizeof(mem_in),
		&mem_in), "Error while setting mem_in");
	HANDLE_CLERROR(clSetKernelArg(crypt_kernel, 1, sizeof(mem_salt),
		&mem_salt), "Error while setting mem_salt");
	HANDLE_CLERROR(clSetKernelArg(crypt_kernel, 2, sizeof(mem_out),
		&mem_out), "Error while setting mem_out");
}
static void create_clobj(size_t gws, struct fmt_main *self)
{
    size_t kpc = gws * v_width;

#define CL_RO CL_MEM_READ_ONLY
#define CL_WO CL_MEM_WRITE_ONLY
#define CL_RW CL_MEM_READ_WRITE

#define CLCREATEBUFFER(_flags, _size)	  \
	clCreateBuffer(context[gpu_id], _flags, _size, NULL, &cl_error); \
	HANDLE_CLERROR(cl_error, "Error allocating GPU memory");

#define CLKERNELARG(kernel, id, arg)	  \
	HANDLE_CLERROR(clSetKernelArg(kernel, id, sizeof(arg), &arg), \
	               "Error setting kernel argument");

#if 0
    fprintf(stderr, "%s("Zu") kpc "Zu"\n", __FUNCTION__, gws, kpc);
#endif
    key_buf_size = PLAINTEXT_LENGTH * kpc;
    inbuffer = mem_calloc(1, key_buf_size);
    host_crack = mem_calloc(kpc, sizeof(pbkdf1_out));

    mem_in = CLCREATEBUFFER(CL_RO, key_buf_size);
    mem_salt = CLCREATEBUFFER(CL_RO, sizeof(pbkdf1_salt));
    mem_state = CLCREATEBUFFER(CL_RW, kpc * sizeof(pbkdf1_state));
    mem_out = CLCREATEBUFFER(CL_WO, kpc * sizeof(pbkdf1_out));

    CLKERNELARG(pbkdf1_init, 0, mem_in);
    CLKERNELARG(pbkdf1_init, 1, mem_salt);
    CLKERNELARG(pbkdf1_init, 2, mem_state);

    CLKERNELARG(pbkdf1_loop, 0, mem_state);

    CLKERNELARG(pbkdf1_final, 0, mem_salt);
    CLKERNELARG(pbkdf1_final, 1, mem_out);
    CLKERNELARG(pbkdf1_final, 2, mem_state);
    global_work_size = gws;
}