/** * @internal * * @brief Tests creation, getting info from and destruction of * buffer wrapper objects. * */ static void create_info_destroy_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLBuffer * b = NULL; CCLErr * err = NULL; size_t buf_size = sizeof(cl_uint) * CCL_TEST_BUFFER_SIZE; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Create regular buffer. */ b = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Get some info and check if the return value is as expected. */ cl_mem_object_type mot; mot = ccl_memobj_get_info_scalar( b, CL_MEM_TYPE, cl_mem_object_type, &err); g_assert_no_error(err); g_assert_cmphex(mot, ==, CL_MEM_OBJECT_BUFFER); cl_mem_flags flags; flags = ccl_memobj_get_info_scalar( b, CL_MEM_FLAGS, cl_mem_flags, &err); g_assert_no_error(err); g_assert_cmphex(flags, ==, CL_MEM_READ_WRITE); size_t mem_size; mem_size = ccl_memobj_get_info_scalar(b, CL_MEM_SIZE, size_t, &err); g_assert_no_error(err); g_assert_cmpuint(mem_size, ==, buf_size); void * host_ptr = NULL; host_ptr = ccl_memobj_get_info_scalar( b, CL_MEM_HOST_PTR, void*, &err); g_assert((err == NULL) || (err->code == CCL_ERROR_INFO_UNAVAILABLE_OCL)); g_assert_cmphex(GPOINTER_TO_UINT(host_ptr), ==, GPOINTER_TO_UINT(NULL)); g_clear_error(&err); cl_context context; context = ccl_memobj_get_info_scalar( b, CL_MEM_CONTEXT, cl_context, &err); g_assert_no_error(err); g_assert_cmphex(GPOINTER_TO_UINT(context), ==, GPOINTER_TO_UINT(ccl_context_unwrap(ctx))); /* Destroy stuff. */ ccl_buffer_destroy(b); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Tests creation (using "full" constructor), getting info from and * destruction of sampler wrapper objects. * */ static void create_full_info_destroy_test() { /* Test variables. */ CCLContext* ctx = NULL; CCLSampler* s = NULL; const cl_sampler_properties sampler_properties[] = { CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE, CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_CLAMP_TO_EDGE, CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, 0}; GError* err = NULL; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Create sampler using "full" constructor. */ s = ccl_sampler_new_full(ctx, sampler_properties, &err); g_assert_no_error(err); /* Get some info and check if the return value is as expected. */ cl_addressing_mode am; am = ccl_sampler_get_info_scalar( s, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode, &err); g_assert_no_error(err); g_assert_cmpuint(am, ==, CL_ADDRESS_CLAMP_TO_EDGE); cl_filter_mode fm; fm = ccl_sampler_get_info_scalar( s, CL_SAMPLER_FILTER_MODE, cl_filter_mode, &err); g_assert_no_error(err); g_assert_cmpuint(fm, ==, CL_FILTER_NEAREST); cl_bool nc; nc = ccl_sampler_get_info_scalar( s, CL_SAMPLER_NORMALIZED_COORDS, cl_bool, &err); g_assert_no_error(err); g_assert_cmpuint(nc, ==, CL_FALSE); cl_context context; context = ccl_sampler_get_info_scalar( s, CL_SAMPLER_CONTEXT, cl_context, &err); g_assert_no_error(err); g_assert_cmphex(GPOINTER_TO_UINT(context), ==, GPOINTER_TO_UINT(ccl_context_unwrap(ctx))); /* Destroy sampler. */ ccl_sampler_destroy(s); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests map/unmap operations in buffer objects. * */ static void map_unmap_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLDevice * d = NULL; CCLBuffer * b = NULL; CCLQueue * q; cl_uint h_in[CCL_TEST_BUFFER_SIZE]; cl_uint * h_out; size_t buf_size = sizeof(cl_uint) * CCL_TEST_BUFFER_SIZE; CCLErr * err = NULL; /* Create a host array, put some stuff in it. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) h_in[i] = g_test_rand_int(); /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue. */ q = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create regular buffer and write data from the host buffer. */ b = ccl_buffer_new( ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, buf_size, h_in, &err); g_assert_no_error(err); /* Map buffer onto host memory. */ h_out = ccl_buffer_enqueue_map( b, q, CL_TRUE, CL_MAP_READ, 0, buf_size, NULL, NULL, &err); g_assert_no_error(err); /* Check data is OK. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) g_assert_cmpuint(h_in[i], ==, h_out[i]); /* Unmap buffer. */ ccl_memobj_enqueue_unmap( (CCLMemObj *) b, q, h_out, NULL, &err); g_assert_no_error(err); /* Free stuff. */ ccl_buffer_destroy(b); ccl_queue_destroy(q); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests buffer wrapping and unwrapping. * */ static void wrap_unwrap_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLBuffer * b = NULL; CCLBuffer * b_aux = NULL; cl_mem buffer = NULL; CCLErr * err = NULL; size_t buf_size = sizeof(cl_uint) * CCL_TEST_BUFFER_SIZE; cl_int status; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Create a buffer using OpenCL functions directly. */ buffer = clCreateBuffer( ccl_context_unwrap(ctx), CL_MEM_READ_ONLY, buf_size, NULL, &status); g_assert_cmpint(status, ==, CL_SUCCESS); /* Wrap buffer. */ b = ccl_buffer_new_wrap(buffer); /* If we now unwrap the wrapper, we must get the originally created * buffer. */ g_assert(buffer == ccl_buffer_unwrap(b)); /* If we again wrap the original buffer... */ b_aux = ccl_buffer_new_wrap(buffer); /* ...we must get the same wrapper... */ g_assert(b == b_aux); /* ... and the buffer wrapper ref count must be 2. */ g_assert_cmpuint(2, ==, ccl_wrapper_ref_count((CCLWrapper *) b)); /* Unref buffer, twice. */ ccl_buffer_unref(b); /* Check that buffer ref count is 1. */ g_assert_cmpuint(1, ==, ccl_wrapper_ref_count((CCLWrapper *) b)); /* Destroy stuff. */ ccl_buffer_destroy(b); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests buffer wrapper class reference counting. * */ static void ref_unref_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLBuffer * b = NULL; CCLErr * err = NULL; size_t buf_size = sizeof(cl_uint) * CCL_TEST_BUFFER_SIZE; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Create regular buffer. */ b = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Increase buffer reference count. */ ccl_memobj_ref(b); /* Check that buffer ref count is 2. */ g_assert_cmpuint(2, ==, ccl_wrapper_ref_count((CCLWrapper *) b)); /* Increase buffer reference count again, this time using helper * macro. */ ccl_buffer_ref(b); /* Check that buffer ref count is 3. */ g_assert_cmpuint(3, ==, ccl_wrapper_ref_count((CCLWrapper *) b)); /* Unref buffer, twice. */ ccl_buffer_unref(b); ccl_buffer_unref(b); /* Check that buffer ref count is 1. */ g_assert_cmpuint(1, ==, ccl_wrapper_ref_count((CCLWrapper *) b)); /* Destroy stuff. */ ccl_buffer_unref(b); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Test memory object destructor callbacks. * */ static void destructor_callback_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLBuffer * b = NULL; CCLErr * err = NULL; GTimer * timer = NULL; cl_bool test_var = CL_FALSE; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Create a buffer. */ b = ccl_buffer_new( ctx, CL_MEM_READ_WRITE, 128 * sizeof(cl_uint), NULL, &err); /* Add destructor callback. */ ccl_memobj_set_destructor_callback( (CCLMemObj *) b, destructor_callback, &test_var, &err); g_assert_no_error(err); /* Destroy buffer. */ ccl_buffer_destroy(b); /* Destroy context. */ ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); /* Wait some more... */ timer = g_timer_new(); while (g_timer_elapsed(timer, NULL) < 2.0); g_timer_stop(timer); g_timer_destroy(timer); /* Confirm that test_var is CL_TRUE. */ g_assert_cmpuint(test_var, ==, CL_TRUE); }
/** * Tests sampler wrapper class reference counting. * */ static void ref_unref_test() { /* Test variables. */ CCLContext* ctx = NULL; CCLSampler* s = NULL; GError* err = NULL; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Create sampler. */ s = ccl_sampler_new(ctx, CL_TRUE, CL_ADDRESS_CLAMP, CL_FILTER_NEAREST, &err); g_assert_no_error(err); /* Increase sampler reference count. */ ccl_sampler_ref(s); /* Check that sampler ref count is 2. */ g_assert_cmpuint(2, ==, ccl_wrapper_ref_count((CCLWrapper*) s)); /* Unref sampler. */ ccl_sampler_unref(s); /* Check that sampler ref count is 1. */ g_assert_cmpuint(1, ==, ccl_wrapper_ref_count((CCLWrapper*) s)); /* Destroy stuff. */ ccl_sampler_unref(s); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Test RNG with client generated seeds in device. * */ static void seed_ext_dev_test() { /* Test variables. */ CCLContext* ctx = NULL; CCLDevice* dev = NULL; CCLQueue* cq = NULL; CCLProgram* prg = NULL; CCLKernel* krnl = NULL; CCLBuffer* seeds_dev = NULL; CCLBuffer* output_dev = NULL; GError* err = NULL; CloRng* rng = NULL; size_t lws = 0; size_t ws = CLO_RNG_TEST_NUM_SEEDS; gchar* src; cl_uchar* host_seeds; /* Get context and device. */ ctx = ccl_context_new_any(&err); g_assert_no_error(err); dev = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create command queue. */ cq = ccl_queue_new(ctx, dev, 0, &err); g_assert_no_error(err); /* Test all RNGs. */ for (cl_uint i = 0; clo_rng_infos[i].name != NULL; ++i) { /* Host seeds must account for the seed size of current RNG. */ size_t seed_size = clo_rng_infos[i].seed_size * CLO_RNG_TEST_NUM_SEEDS; host_seeds = g_slice_alloc(seed_size); /* Initialize host seeds with any value. */ for (cl_uint i = 0; i < seed_size; ++i) host_seeds[i] = (cl_uchar) (((i + 1) * 3) & 0xFF); /* Allocate memory for device seeds and copy host seeds. */ seeds_dev = ccl_buffer_new( ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, seed_size, host_seeds, &err); g_assert_no_error(err); /* Create RNG object. */ rng = clo_rng_new(clo_rng_infos[i].name, CLO_RNG_SEED_EXT_DEV, seeds_dev, CLO_RNG_TEST_NUM_SEEDS, CLO_RNG_TEST_INIT_SEED, NULL, ctx, cq, &err); g_assert_no_error(err); /* Get RNG kernels source. */ src = g_strconcat( clo_rng_get_source(rng), CLO_RNG_TEST_SRC, NULL); /* Create and build program. */ prg = ccl_program_new_from_source(ctx, src, &err); g_assert_no_error(err); ccl_program_build(prg, NULL, &err); g_assert_no_error(err); /* Create output buffer. */ output_dev = ccl_buffer_new(ctx, CL_MEM_WRITE_ONLY, CLO_RNG_TEST_NUM_SEEDS * sizeof(cl_ulong), NULL, &err); g_assert_no_error(err); /* Get kernel from program. */ krnl = ccl_program_get_kernel(prg, CLO_RNG_TEST_KERNEL, &err); g_assert_no_error(err); /* Get a "nice" local worksize. */ ccl_kernel_suggest_worksizes( krnl, dev, 1, &ws, NULL, &lws, &err); g_assert_no_error(err); /* Execute kernel. */ ccl_kernel_set_args_and_enqueue_ndrange( krnl, cq, 1, NULL, &ws, &lws, NULL, &err, seeds_dev, output_dev, NULL); g_assert_no_error(err); /* Release this iteration stuff. */ g_slice_free1(seed_size, host_seeds); g_free(src); ccl_buffer_destroy(seeds_dev); ccl_buffer_destroy(output_dev); ccl_program_destroy(prg); clo_rng_destroy(rng); } /* Destroy queue and context. */ ccl_queue_destroy(cq); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests memory object migration. * */ static void migrate_test() { /* Test variables. */ CCLPlatforms * ps; CCLPlatform * p; CCLContext * ctx = NULL; CCLDevice * d = NULL; CCLBuffer * b = NULL; CCLQueue * q; size_t buf_size = sizeof(cl_char8) * CCL_TEST_BUFFER_SIZE; CCLErr * err = NULL; /* Get a context which supports OpenCL 1.2 if possible. */ ps = ccl_platforms_new(&err); g_assert_no_error(err); for (guint i = 0; i < ccl_platforms_count(ps); ++i) { p = ccl_platforms_get(ps, i); cl_uint ocl_ver = ccl_platform_get_opencl_version(p, &err); if (ocl_ver >= 120) { ctx = ccl_context_new_from_devices( ccl_platform_get_num_devices(p, NULL), ccl_platform_get_all_devices(p, NULL), &err); g_assert_no_error(err); break; } } /* If not possible to find a 1.2 or better context, finish this * test. */ if (ctx == NULL) { g_test_message("'%s' test not performed because no platform " \ "with OpenCL 1.2 support was found", CCL_STRD); ccl_platforms_destroy(ps); return; } /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue associated with first device in * context. */ q = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create regular buffer. */ b = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Assign buffer to first device in context (via the command * queue). */ ccl_memobj_enqueue_migrate((CCLMemObj **) &b, 1, q, 0, NULL, &err); g_assert_no_error(err); /* Migrate buffer to host. */ ccl_memobj_enqueue_migrate( (CCLMemObj **) &b, 1, q, CL_MIGRATE_MEM_OBJECT_HOST, NULL, &err); g_assert_no_error(err); /* Wait for queue to finish... */ ccl_queue_finish(q, &err); g_assert_no_error(err); /* Free stuff. */ ccl_buffer_destroy(b); ccl_queue_destroy(q); ccl_context_destroy(ctx); ccl_platforms_destroy(ps); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests buffer fill. * */ static void fill_test() { /* Test variables. */ CCLPlatforms * ps; CCLPlatform * p; CCLContext * ctx = NULL; CCLDevice * d = NULL; CCLBuffer * b = NULL; CCLQueue * q; cl_char8 h[CCL_TEST_BUFFER_SIZE]; cl_char8 pattern = {{ 1, -1, 5, 4, -12, 3, 7, -20 }}; size_t buf_size = sizeof(cl_char8) * CCL_TEST_BUFFER_SIZE; CCLErr * err = NULL; /* Get a context which supports OpenCL 1.2, if possible. */ ps = ccl_platforms_new(&err); g_assert_no_error(err); for (guint i = 0; i < ccl_platforms_count(ps); ++i) { p = ccl_platforms_get(ps, i); cl_uint ocl_ver = ccl_platform_get_opencl_version(p, &err); if (ocl_ver >= 120) { ctx = ccl_context_new_from_devices( ccl_platform_get_num_devices(p, NULL), ccl_platform_get_all_devices(p, NULL), &err); g_assert_no_error(err); break; } } /* If not possible to find a 1.2 or better context, finish this * test. */ if (ctx == NULL) { g_test_message("'%s' test not performed because no platform " \ "with OpenCL 1.2 support was found", CCL_STRD); ccl_platforms_destroy(ps); return; } /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue. */ q = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create regular buffer. */ b = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Fill buffer with pattern. */ ccl_buffer_enqueue_fill( b, q, &pattern, sizeof(cl_char8), 0, buf_size, NULL, &err); g_assert_no_error(err); /* Read data back to host. */ ccl_buffer_enqueue_read(b, q, CL_TRUE, 0, buf_size, h, NULL, &err); g_assert_no_error(err); /* Check data is OK. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) for (guint j = 0; j < 8; ++j) g_assert_cmpuint(h[i].s[j], ==, pattern.s[j]); /* Free stuff. */ ccl_buffer_destroy(b); ccl_queue_destroy(q); ccl_context_destroy(ctx); ccl_platforms_destroy(ps); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests the ccl_buffer_new_from_region() function. * */ static void create_from_region_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLDevice * dev = NULL; CCLQueue * cq = NULL; CCLBuffer * buf = NULL; CCLBuffer * subbuf = NULL; CCLEvent * evt = NULL; CCLEventWaitList ewl = NULL; CCLErr * err = NULL; cl_ulong * hbuf; cl_ulong * hsubbuf; cl_uint min_align; size_t siz_buf; size_t siz_subbuf; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Get first device in context. */ dev = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Get minimum alignment for sub-buffer in bits. */ min_align = ccl_device_get_info_scalar( dev, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint, &err); g_assert_no_error(err); /* Determine buffer and sub-buffer sizes (divide by 64 because its * the number of bits in cl_ulong). */ siz_subbuf = sizeof(cl_ulong) * min_align / 64; siz_buf = 4 * siz_subbuf; /* Allocate memory for host buffer and host sub-buffer. */ hbuf = g_slice_alloc(siz_buf); hsubbuf = g_slice_alloc(siz_subbuf); /* Initialize initial host buffer. */ for (cl_uint i = 0; i < siz_buf / sizeof(cl_ulong); ++i) hbuf[i] = g_test_rand_int(); /* Create a command queue. */ cq = ccl_queue_new(ctx, dev, 0, &err); g_assert_no_error(err); /* Create a regular buffer, put some data in it. */ buf = ccl_buffer_new( ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, siz_buf, hbuf, &err); g_assert_no_error(err); /* Create sub-buffer from indexes 16 to 31 (16 positions) of * original buffer. */ subbuf = ccl_buffer_new_from_region( buf, 0, siz_subbuf, siz_subbuf, &err); g_assert_no_error(err); /* Get data in sub-buffer to a new host buffer. */ evt = ccl_buffer_enqueue_read( subbuf, cq, CL_FALSE, 0, siz_subbuf, hsubbuf, NULL, &err); g_assert_no_error(err); /* Wait for read to be complete. */ ccl_event_wait(ccl_ewl(&ewl, evt, NULL), &err); g_assert_no_error(err); /* Check that expected values were successfully read. */ for (cl_uint i = 0; i < siz_subbuf / sizeof(cl_ulong); ++i) g_assert_cmpuint( hsubbuf[i], ==, hbuf[i + siz_subbuf / sizeof(cl_ulong)]); /* Destroy stuff. */ ccl_buffer_destroy(buf); ccl_buffer_destroy(subbuf); ccl_queue_destroy(cq); ccl_context_destroy(ctx); g_slice_free1(siz_buf, hbuf); g_slice_free1(siz_subbuf, hsubbuf); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @internal * * @brief Tests rect buffer operations. * */ static void rect_read_write_copy_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLDevice * d = NULL; CCLBuffer * b1 = NULL; CCLBuffer * b2 = NULL; CCLQueue * cq; cl_uchar h1[CCL_TEST_BUFFER_SIZE * CCL_TEST_BUFFER_SIZE]; cl_uchar h2[CCL_TEST_BUFFER_SIZE * CCL_TEST_BUFFER_SIZE]; size_t buf_size = sizeof(cl_uchar) * sizeof(cl_uchar) * CCL_TEST_BUFFER_SIZE * CCL_TEST_BUFFER_SIZE; CCLErr * err = NULL; const size_t origin[] = {0, 0, 0}; const size_t region[] = {CCL_TEST_BUFFER_SIZE * sizeof(cl_uchar), CCL_TEST_BUFFER_SIZE * sizeof(cl_uchar), 1}; /* Create a "2D" host array, put some stuff in it. */ for (cl_uint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) for (cl_uint j = 0; j < CCL_TEST_BUFFER_SIZE; ++j) h1[i * CCL_TEST_BUFFER_SIZE + j] = (cl_uchar) (g_test_rand_int() % 0xFF); /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue. */ cq = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create device buffers. */ b1 = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); b2 = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Write "rect" data to first buffer in device. */ ccl_buffer_enqueue_write_rect( b1, cq, CL_TRUE, origin, origin, region, 0, 0, 0, 0, h1, NULL, &err); g_assert_no_error(err); /* Copy "rect" data from first buffer to second buffer. */ ccl_buffer_enqueue_copy_rect( b1, b2, cq, origin, origin, region, 0, 0, 0, 0, NULL, &err); g_assert_no_error(err); /* Read data "rect" back to host from the second buffer. */ ccl_buffer_enqueue_read_rect( b2, cq, CL_TRUE, origin, origin, region, 0, 0, 0, 0, h2, NULL, &err); g_assert_no_error(err); /* Check data is OK doing a flat comparison. */ for (cl_uint i = 0; i < CCL_TEST_BUFFER_SIZE * CCL_TEST_BUFFER_SIZE; ++i) g_assert_cmpuint(h1[i], ==, h2[i]); /* Free stuff. */ ccl_buffer_destroy(b1); ccl_buffer_destroy(b2); ccl_queue_destroy(cq); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Kernel info main function. * * @param[in] argc Number of command line arguments. * @param[in] argv Command line arguments. * @return ::CCL_SUCCESS if program returns with no error, or another * ::CCLErrorCode value otherwise. * */ int main(int argc, char *argv[]) { /* ***************** */ /* Program variables */ /* ***************** */ /* Function and program return status. */ int status; /* Error management. */ GError *err = NULL; /* Context wrapper. */ CCLContext* ctx = NULL; /* Program wrapper. */ CCLProgram* prg = NULL; /* Kernel wrapper. */ CCLKernel* krnl = NULL; /* Device wrapper. */ CCLDevice* dev = NULL; /* Device filters. */ CCLDevSelFilters filters = NULL; /* Default device index. */ cl_int dev_idx = -1; /* OpenCL version. */ double ocl_ver; /* Kernel workgroup info variables. */ size_t k_wg_size; size_t k_pref_wg_size_mult; size_t* k_compile_wg_size; cl_ulong k_loc_mem_size; cl_ulong k_priv_mem_size; /* ************************** */ /* Parse command line options */ /* ************************** */ /* If version was requested, output version and exit. */ if ((argc == 2) && (g_strcmp0("--version", argv[1]) == 0)) { ccl_common_version_print("ccl_kerninfo"); exit(0); } ccl_if_err_create_goto(err, CCL_ERROR, (argc < 3) || (argc > 4), CCL_ERROR_ARGS, error_handler, "Usage: %s <program_file> <kernel_name> [device_index]\n", argv[0]); if (argc == 4) dev_idx = atoi(argv[3]); /* ********************************************* */ /* Initialize OpenCL variables and build program */ /* ********************************************* */ /* Select a context/device. */ ccl_devsel_add_dep_filter( &filters, ccl_devsel_dep_menu, (dev_idx == -1) ? NULL : (void*) &dev_idx); ctx = ccl_context_new_from_filters(&filters, &err); ccl_if_err_goto(err, error_handler); /* Get program which contains kernel. */ prg = ccl_program_new_from_source_file(ctx, argv[1], &err); ccl_if_err_goto(err, error_handler); /* Build program. */ ccl_program_build(prg, NULL, &err); ccl_if_err_goto(err, error_handler); /* Get kernel */ krnl = ccl_program_get_kernel(prg, argv[2], &err); ccl_if_err_goto(err, error_handler); /* Get the device. */ dev = ccl_context_get_device(ctx, 0, &err); ccl_if_err_goto(err, error_handler); /* Check platform OpenCL version. */ ocl_ver = ccl_kernel_get_opencl_version(krnl, &err); ccl_if_err_goto(err, error_handler); /* *************************** */ /* Get and print kernel info */ /* *************************** */ g_printf("\n ======================== Static Kernel Information =======================\n\n"); k_wg_size = ccl_kernel_get_workgroup_info_scalar( krnl, dev, CL_KERNEL_WORK_GROUP_SIZE, size_t, &err); ccl_if_err_goto(err, error_handler); g_printf(" Maximum workgroup size : %lu\n", (unsigned long) k_wg_size); /* Only show info about CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE * if OpenCL version of the underlying platform is >= 1.1. */ if (ocl_ver >= 110) { k_pref_wg_size_mult = ccl_kernel_get_workgroup_info_scalar(krnl, dev, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, size_t, &err); ccl_if_err_goto(err, error_handler); g_printf(" Preferred multiple of workgroup size : %lu\n", (unsigned long) k_pref_wg_size_mult); } k_compile_wg_size = ccl_kernel_get_workgroup_info_array(krnl, dev, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, size_t*, &err); ccl_if_err_goto(err, error_handler); g_printf(" WG size in __attribute__ qualifier : (%lu, %lu, %lu)\n", (unsigned long) k_compile_wg_size[0], (unsigned long) k_compile_wg_size[1], (unsigned long) k_compile_wg_size[2]); k_loc_mem_size = ccl_kernel_get_workgroup_info_scalar(krnl, dev, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong, &err); ccl_if_err_goto(err, error_handler); g_printf(" Local memory used by kernel : %lu bytes\n", (unsigned long) k_loc_mem_size); k_priv_mem_size = ccl_kernel_get_workgroup_info_scalar(krnl, dev, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong, &err); ccl_if_err_goto(err, error_handler); g_printf(" Min. private mem. used by each workitem : %lu bytes\n", (unsigned long) k_priv_mem_size); g_printf("\n"); /* ************** */ /* Error handling */ /* ************** */ /* If we get here, no need for error checking, jump to cleanup. */ g_assert(err == NULL); status = CCL_SUCCESS; goto cleanup; error_handler: /* If we got here there was an error, verify that it is so. */ g_assert(err != NULL); g_fprintf(stderr, "%s\n", err->message); status = (err->domain == CCL_ERROR) ? err->code : CCL_ERROR_OTHER; g_error_free(err); cleanup: /* *********** */ /* Free stuff! */ /* *********** */ if (prg != NULL) ccl_program_destroy(prg); if (ctx != NULL) ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_return_val_if_fail(ccl_wrapper_memcheck(), CCL_ERROR_OTHER); /* Return status. */ return status; }
/** * @internal * * @brief Tests copy operations from one buffer to another. * */ static void copy_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLDevice * d = NULL; CCLBuffer * b1 = NULL; CCLBuffer * b2 = NULL; CCLQueue * q; cl_long h1[CCL_TEST_BUFFER_SIZE]; cl_long h2[CCL_TEST_BUFFER_SIZE]; size_t buf_size = sizeof(cl_long) * CCL_TEST_BUFFER_SIZE; CCLErr * err = NULL; /* Create a host array, put some stuff in it. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) h1[i] = g_test_rand_int(); /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue. */ q = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create regular buffer and write data from the host buffer. */ b1 = ccl_buffer_new( ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, buf_size, h1, &err); g_assert_no_error(err); /* Create another buffer, double the size. */ b2 = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, 2 * buf_size, NULL, &err); g_assert_no_error(err); /* Copy data from first buffer to second buffer, using an offset on * the second buffer. */ ccl_buffer_enqueue_copy( b1, b2, q, 0, buf_size / 2, buf_size, NULL, &err); g_assert_no_error(err); /* Read data back to host from the second buffer. */ ccl_buffer_enqueue_read( b2, q, CL_TRUE, buf_size / 2, buf_size, h2, NULL, &err); g_assert_no_error(err); /* Check data is OK. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) g_assert_cmpuint(h1[i], ==, h2[i]); /* Free stuff. */ ccl_buffer_destroy(b1); ccl_buffer_destroy(b2); ccl_queue_destroy(q); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Test RNG with GID-based device generated seeds. * */ static void seed_dev_gid_test() { /* Test variables. */ CCLContext* ctx = NULL; CCLDevice* dev = NULL; CCLQueue* cq = NULL; CCLProgram* prg = NULL; CCLKernel* krnl = NULL; CCLBuffer* seeds_dev = NULL; CCLBuffer* output_dev = NULL; GError* err = NULL; CloRng* rng = NULL; size_t lws = 0; size_t ws = CLO_RNG_TEST_NUM_SEEDS; gchar* src; /* Get context and device. */ ctx = ccl_context_new_any(&err); g_assert_no_error(err); dev = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create command queue. */ cq = ccl_queue_new(ctx, dev, 0, &err); g_assert_no_error(err); /* Test all RNGs. */ for (cl_uint i = 0; clo_rng_infos[i].name != NULL; ++i) { /* Create RNG object. */ rng = clo_rng_new(clo_rng_infos[i].name, CLO_RNG_SEED_DEV_GID, NULL, CLO_RNG_TEST_NUM_SEEDS, CLO_RNG_TEST_INIT_SEED, CLO_RNG_TEST_HASH, ctx, cq, &err); g_assert_no_error(err); /* Get RNG seeds device buffer. */ seeds_dev = clo_rng_get_device_seeds(rng); /* Get RNG kernels source. */ src = g_strconcat( clo_rng_get_source(rng), CLO_RNG_TEST_SRC, NULL); /* Create and build program. */ prg = ccl_program_new_from_source(ctx, src, &err); g_assert_no_error(err); ccl_program_build(prg, NULL, &err); g_assert_no_error(err); /* Create output buffer. */ output_dev = ccl_buffer_new(ctx, CL_MEM_WRITE_ONLY, CLO_RNG_TEST_NUM_SEEDS * sizeof(cl_ulong), NULL, &err); g_assert_no_error(err); /* Get kernel from program. */ krnl = ccl_program_get_kernel(prg, CLO_RNG_TEST_KERNEL, &err); g_assert_no_error(err); /* Get a "nice" local worksize. */ ccl_kernel_suggest_worksizes( krnl, dev, 1, &ws, NULL, &lws, &err); g_assert_no_error(err); /* Execute kernel. */ ccl_kernel_set_args_and_enqueue_ndrange( krnl, cq, 1, NULL, &ws, &lws, NULL, &err, seeds_dev, output_dev, NULL); g_assert_no_error(err); /* Release this iteration stuff. */ g_free(src); ccl_buffer_destroy(output_dev); ccl_program_destroy(prg); clo_rng_destroy(rng); } /* Destroy queue and context. */ ccl_queue_destroy(cq); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Image filter main function. * */ int main(int argc, char * argv[]) { /* Wrappers for OpenCL objects. */ CCLContext * ctx; CCLDevice * dev; CCLImage * img_in; CCLImage * img_out; CCLQueue * queue; CCLProgram * prg; CCLKernel * krnl; CCLSampler * smplr; /* Device selected specified in the command line. */ int dev_idx = -1; /* Error handling object (must be initialized to NULL). */ CCLErr * err = NULL; /* Does selected device support images? */ cl_bool image_ok; /* Image data in host. */ unsigned char * input_image; unsigned char * output_image; /* Image properties. */ int width, height, n_channels; /* Image file write status. */ int file_write_status; /* Image parameters. */ cl_image_format image_format = { CL_RGBA, CL_UNSIGNED_INT8 }; /* Origin and region of complete image. */ size_t origin[3] = { 0, 0, 0 }; size_t region[3]; /* Real worksize. */ size_t real_ws[2]; /* Global and local worksizes. */ size_t gws[2]; size_t lws[2]; /* Check arguments. */ if (argc < 2) { ERROR_MSG_AND_EXIT("Usage: image_filter <image_file> [device_index]"); } else if (argc >= 3) { /* Check if a device was specified in the command line. */ dev_idx = atoi(argv[2]); } /* Load image. */ input_image = stbi_load(argv[1], &width, &height, &n_channels, 4); if (!input_image) ERROR_MSG_AND_EXIT(stbi_failure_reason()); /* Real work size. */ real_ws[0] = width; real_ws[1] = height; /* Set image region. */ region[0] = width; region[1] = height; region[2] = 1; /* Create context using device selected from menu. */ ctx = ccl_context_new_from_menu_full(&dev_idx, &err); HANDLE_ERROR(err); /* Get first device in context. */ dev = ccl_context_get_device(ctx, 0, &err); HANDLE_ERROR(err); /* Ask device if it supports images. */ image_ok = ccl_device_get_info_scalar( dev, CL_DEVICE_IMAGE_SUPPORT, cl_bool, &err); HANDLE_ERROR(err); if (!image_ok) ERROR_MSG_AND_EXIT("Selected device doesn't support images."); /* Create a command queue. */ queue = ccl_queue_new(ctx, dev, 0, &err); HANDLE_ERROR(err); /* Create 2D input image using loaded image data. */ img_in = ccl_image_new(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &image_format, input_image, &err, "image_type", (cl_mem_object_type) CL_MEM_OBJECT_IMAGE2D, "image_width", (size_t) width, "image_height", (size_t) height, NULL); HANDLE_ERROR(err); /* Create 2D output image. */ img_out = ccl_image_new(ctx, CL_MEM_WRITE_ONLY, &image_format, NULL, &err, "image_type", (cl_mem_object_type) CL_MEM_OBJECT_IMAGE2D, "image_width", (size_t) width, "image_height", (size_t) height, NULL); HANDLE_ERROR(err); /* Create program from kernel source and compile it. */ prg = ccl_program_new_from_source(ctx, FILTER_KERNEL, &err); HANDLE_ERROR(err); ccl_program_build(prg, NULL, &err); HANDLE_ERROR(err); /* Get kernel wrapper. */ krnl = ccl_program_get_kernel(prg, "do_filter", &err); HANDLE_ERROR(err); /* Determine nice local and global worksizes. */ ccl_kernel_suggest_worksizes(krnl, dev, 2, real_ws, gws, lws, &err); HANDLE_ERROR(err); /* Show information to user. */ printf("\n * Image size: %d x %d, %d channels\n", width, height, n_channels); printf(" * Global work-size: (%d, %d)\n", (int) gws[0], (int) gws[1]); printf(" * Local work-size: (%d, %d)\n", (int) lws[0], (int) lws[1]); /* Create sampler (this could also be created in-kernel). */ smplr = ccl_sampler_new(ctx, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err); HANDLE_ERROR(err); /* Apply filter. */ ccl_kernel_set_args_and_enqueue_ndrange( krnl, queue, 2, NULL, gws, lws, NULL, &err, img_in, img_out, smplr, NULL); HANDLE_ERROR(err); /* Allocate space for output image. */ output_image = (unsigned char *) malloc(width * height * 4 * sizeof(unsigned char)); /* Read image data back to host. */ ccl_image_enqueue_read(img_out, queue, CL_TRUE, origin, region, 0, 0, output_image, NULL, &err); HANDLE_ERROR(err); /* Write image to file. */ file_write_status = stbi_write_png(IMAGE_FILE, width, height, 4, output_image, width * 4); /* Give feedback. */ if (file_write_status) { fprintf(stdout, "\nImage saved in file '" IMAGE_FILE "'\n"); } else { ERROR_MSG_AND_EXIT("Unable to save image in file."); } /* Release host images. */ free(output_image); stbi_image_free(input_image); /* Release wrappers. */ ccl_image_destroy(img_in); ccl_image_destroy(img_out); ccl_sampler_destroy(smplr); ccl_program_destroy(prg); ccl_queue_destroy(queue); ccl_context_destroy(ctx); /* Check all wrappers have been destroyed. */ assert(ccl_wrapper_memcheck()); /* Terminate. */ return EXIT_SUCCESS; }
/** * Tests basic read/write operations from/to buffer objects. * */ static void buffer_read_write() { /* Test variables. */ CCLContext* ctx = NULL; CCLDevice* d = NULL; CCLBuffer* b = NULL; CCLQueue* q; cl_uint h_in[CCL_TEST_BUFFER_SIZE]; cl_uint h_out[CCL_TEST_BUFFER_SIZE]; size_t buf_size = sizeof(cl_uint) * CCL_TEST_BUFFER_SIZE; GError* err = NULL; /* Create a host array, put some stuff in it. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) h_in[i] = g_test_rand_int(); /* Get a context with any device. */ ctx = ccl_context_new_any(&err); g_assert_no_error(err); /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue. */ q = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create regular buffer and write data from the host buffer. */ b = ccl_buffer_new(ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, buf_size, h_in, &err); g_assert_no_error(err); /* Read data back to host. */ ccl_buffer_enqueue_read(b, q, CL_TRUE, 0, buf_size, (void*) h_out, NULL, &err); g_assert_no_error(err); /* Check data is OK. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) g_assert_cmpuint(h_in[i], ==, h_out[i]); /* Set some other data in host array. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) h_in[i] = g_test_rand_int(); /* Write it explicitly to buffer. */ ccl_buffer_enqueue_write(b, q, CL_TRUE, 0, buf_size, (void*) h_in, NULL, &err); g_assert_no_error(err); /* Read new data to host. */ ccl_buffer_enqueue_read(b, q, CL_TRUE, 0, buf_size, (void*) h_out, NULL, &err); g_assert_no_error(err); /* Check data is OK. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) g_assert_cmpuint(h_in[i], ==, h_out[i]); /* Free stuff. */ ccl_buffer_destroy(b); ccl_queue_destroy(q); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Tests creation, getting info from and destruction of * profiler objects, and their relationship with context, device and * queue wrapper objects. * */ static void create_add_destroy_test() { /* Test variables. */ CCLErr* err = NULL; CCLBuffer* buf1 = NULL; CCLBuffer* buf2 = NULL; CCLProf* prof = NULL; CCLContext* ctx = NULL; CCLDevice* d = NULL; CCLQueue* cq1 = NULL; CCLQueue* cq2 = NULL; CCLEvent* evt = NULL; CCLEventWaitList ewl = NULL; size_t buf_size = 8 * sizeof(cl_short); cl_short hbuf[8] = {1, 2, 3, 4, 5, 6, 7, 8}; cl_ulong duration, eff_duration; double time_elapsed; /* Create a new profile object. */ prof = ccl_prof_new(); /* Get a context and a device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create two command queue wrappers. */ cq1 = ccl_queue_new(ctx, d, CL_QUEUE_PROFILING_ENABLE, &err); g_assert_no_error(err); cq2 = ccl_queue_new(ctx, d, CL_QUEUE_PROFILING_ENABLE, &err); g_assert_no_error(err); /* Create device buffers. */ buf1 = ccl_buffer_new(ctx, CL_MEM_READ_ONLY, buf_size, NULL, &err); g_assert_no_error(err); buf2 = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Start profile object timer. */ ccl_prof_start(prof); /* Transfer data to buffer. */ evt = ccl_buffer_enqueue_write( buf1, cq1, CL_FALSE, 0, buf_size, hbuf, NULL, &err); g_assert_no_error(err); /* Transfer data from one buffer to another. */ evt = ccl_buffer_enqueue_copy(buf1, buf2, cq2, 0, 0, buf_size, ccl_ewl(&ewl, evt, NULL), &err); g_assert_no_error(err); /* Wait for copy. */ ccl_event_wait(ccl_ewl(&ewl, evt, NULL), &err); g_assert_no_error(err); /* Stop profile object timer. */ ccl_prof_stop(prof); /* Add both queues to profile object. */ ccl_prof_add_queue(prof, "A Queue", cq1); ccl_prof_add_queue(prof, "Another Queue", cq2); /* Process queues. */ ccl_prof_calc(prof, &err); g_assert_no_error(err); /* Request some profiling information. */ time_elapsed = ccl_prof_time_elapsed(prof); duration = ccl_prof_get_duration(prof); eff_duration = ccl_prof_get_eff_duration(prof); g_debug("Profiling time elapsed: %lf", time_elapsed); g_debug("Profiling duration: %d", (cl_int) duration); g_debug("Profiling eff. duration: %d", (cl_int) eff_duration); /* Destroy buffers. */ ccl_buffer_destroy(buf1); ccl_buffer_destroy(buf2); /* Unref cq1, which should not be destroyed because it is held * by the profile object. */ ccl_queue_destroy(cq1); /* Destroy the profile object, which will also destroy cq1. cq2 * will me merely unrefed and must still be explicitly destroyed. */ ccl_prof_destroy(prof); /* Destroy cq2. */ ccl_queue_destroy(cq2); /* Destroy the context. */ ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Tests devquery module helper functions. * */ static void helpers_test() { CCLPlatforms* platfs = NULL; CCLPlatform* p = NULL; CCLDevice* d = NULL; GError* err = NULL; guint num_devs; guint num_platfs; CCLWrapperInfo* info; gchar param_value_str[CCL_TEST_DEVQUERY_MAXINFOLEN]; /* Get platforms. */ platfs = ccl_platforms_new(&err); if (err == NULL) { /* Number of platforms. */ num_platfs = ccl_platforms_count(platfs); g_debug("* Found %d OpenCL platforms", num_platfs); /* Cycle through platforms. */ for (guint i = 0; i < num_platfs; i++) { /* Get current platform. */ p = ccl_platforms_get(platfs, i); g_debug(">> Platform %d:", i); /* Get number of devices. */ num_devs = ccl_platform_get_num_devices(p, &err); /* Only test for device information if device count was * successfully obtained. */ if (err != NULL) { g_test_message("Error obtaining number of devices for platform %d (%s).", i, err->message); g_clear_error(&err); } else { g_debug("==== # Devs : %d", num_devs); /* Cycle through devices in platform. */ for (guint j = 0; j < num_devs; j++) { /* Get current device. */ d = ccl_platform_get_device(p, j, &err); g_assert_no_error(err); g_debug("====== Device #%d", j); for (gint k = 0; k < ccl_devquery_info_map_size; k++) { info = ccl_device_get_info(d, ccl_devquery_info_map[k].device_info, &err); if (err == NULL) { g_debug("\t%s : %s", ccl_devquery_info_map[k].param_name, ccl_devquery_info_map[k].format( info, param_value_str, CCL_TEST_DEVQUERY_MAXINFOLEN, ccl_devquery_info_map[k].units)); } else { g_clear_error(&err); g_debug("\t%s : %s", ccl_devquery_info_map[k].param_name, "N/A"); } } } } } /* Destroy list of platforms. */ ccl_platforms_destroy(platfs); } else { /* Unable to get any OpenCL platforms, test can't pass. */ g_test_message("Test failed due to following error: %s", err->message); g_test_fail(); } /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Cellular automata sample main function. * */ int main(int argc, char* argv[]) { /* Wrappers for OpenCL objects. */ CCLContext* ctx; CCLDevice* dev; CCLImage* img1; CCLImage* img2; CCLProgram* prg; CCLKernel* krnl; CCLEvent* evt1; CCLEvent* evt2; /* Other variables. */ CCLEventWaitList ewl = NULL; /* Profiler object. */ CCLProf* prof; /* Output images filename. */ char* filename; /* Selected device, may be given in command line. */ int dev_idx = -1; /* Error handling object (must be NULL). */ GError* err = NULL; /* Does selected device support images? */ cl_bool image_ok; /* Initial sim state. */ cl_uchar4* input_image; /* Simulation states. */ cl_uchar4** output_images; /* RNG seed, may be given in command line. */ unsigned int seed; /* Image file write status. */ int file_write_status; /* Image format. */ cl_image_format image_format = { CL_RGBA, CL_UNSIGNED_INT8 }; /* Thread data. */ struct thread_data td; /* Global and local worksizes. */ size_t gws[2]; size_t lws[2]; /* Threads. */ GThread* comm_thread; GThread* exec_thread; /* Check arguments. */ if (argc >= 2) { /* Check if a device was specified in the command line. */ dev_idx = atoi(argv[1]); } if (argc >= 3) { /* Check if a RNG seed was specified. */ seed = atoi(argv[2]); } else { seed = (unsigned int) time(NULL); } /* Initialize RNG. */ srand(seed); /* Create random initial state. */ input_image = (cl_uchar4*) malloc(CA_WIDTH * CA_HEIGHT * sizeof(cl_uchar4)); for (cl_uint i = 0; i < CA_WIDTH * CA_HEIGHT; ++i) { cl_uchar state = (rand() & 0x3) ? 0xFF : 0x00; input_image[i] = (cl_uchar4) {{ state, state, state, 0xFF }}; } /* Allocate space for simulation results. */ output_images = (cl_uchar4**) malloc((CA_ITERS + 1) * sizeof(cl_uchar4*)); for (cl_uint i = 0; i < CA_ITERS + 1; ++i) output_images[i] = (cl_uchar4*) malloc(CA_WIDTH * CA_HEIGHT * sizeof(cl_uchar4)); /* Create context using device selected from menu. */ ctx = ccl_context_new_from_menu_full(&dev_idx, &err); HANDLE_ERROR(err); /* Get first device in context. */ dev = ccl_context_get_device(ctx, 0, &err); HANDLE_ERROR(err); /* Ask device if it supports images. */ image_ok = ccl_device_get_info_scalar( dev, CL_DEVICE_IMAGE_SUPPORT, cl_bool, &err); HANDLE_ERROR(err); if (!image_ok) ERROR_MSG_AND_EXIT("Selected device doesn't support images."); /* Create command queues. */ queue_exec = ccl_queue_new(ctx, dev, CL_QUEUE_PROFILING_ENABLE, &err); HANDLE_ERROR(err); queue_comm = ccl_queue_new(ctx, dev, CL_QUEUE_PROFILING_ENABLE, &err); HANDLE_ERROR(err); /* Create 2D image for initial state. */ img1 = ccl_image_new(ctx, CL_MEM_READ_WRITE, &image_format, NULL, &err, "image_type", (cl_mem_object_type) CL_MEM_OBJECT_IMAGE2D, "image_width", (size_t) CA_WIDTH, "image_height", (size_t) CA_HEIGHT, NULL); HANDLE_ERROR(err); /* Create another 2D image for double buffering. */ img2 = ccl_image_new(ctx, CL_MEM_READ_WRITE, &image_format, NULL, &err, "image_type", (cl_mem_object_type) CL_MEM_OBJECT_IMAGE2D, "image_width", (size_t) CA_WIDTH, "image_height", (size_t) CA_HEIGHT, NULL); HANDLE_ERROR(err); /* Create program from kernel source and compile it. */ prg = ccl_program_new_from_source(ctx, CA_KERNEL, &err); HANDLE_ERROR(err); ccl_program_build(prg, NULL, &err); HANDLE_ERROR(err); /* Get kernel wrapper. */ krnl = ccl_program_get_kernel(prg, "ca", &err); HANDLE_ERROR(err); /* Determine nice local and global worksizes. */ ccl_kernel_suggest_worksizes(krnl, dev, 2, real_ws, gws, lws, &err); HANDLE_ERROR(err); printf("\n * Global work-size: (%d, %d)\n", (int) gws[0], (int) gws[1]); printf(" * Local work-size: (%d, %d)\n", (int) lws[0], (int) lws[1]); /* Create thread communication queues. */ comm_thread_queue = g_async_queue_new(); exec_thread_queue = g_async_queue_new(); host_thread_queue = g_async_queue_new(); /* Setup thread data. */ td.krnl = krnl; td.img1 = img1; td.img2 = img2; td.gws = gws; td.lws = lws; td.output_images = output_images; /* Create threads. */ exec_thread = g_thread_new("exec_thread", exec_func, &td); comm_thread = g_thread_new("comm_thread", comm_func, &td); /* Start profiling. */ prof = ccl_prof_new(); ccl_prof_start(prof); /* Write initial state. */ ccl_image_enqueue_write(img1, queue_comm, CL_TRUE, origin, region, 0, 0, input_image, NULL, &err); HANDLE_ERROR(err); /* Run CA_ITERS iterations of the CA. */ for (cl_uint i = 0; i < CA_ITERS; ++i) { /* Send message to comms thread. */ g_async_queue_push(comm_thread_queue, &go_msg); /* Send message to exec thread. */ g_async_queue_push(exec_thread_queue, &go_msg); /* Get event wrappers from both threads. */ evt1 = (CCLEvent*) g_async_queue_pop(host_thread_queue); evt2 = (CCLEvent*) g_async_queue_pop(host_thread_queue); /* Can't continue until this iteration is over. */ ccl_event_wait_list_add(&ewl, evt1, evt2, NULL); /* Wait for events. */ ccl_event_wait(&ewl, &err); HANDLE_ERROR(err); } /* Send message to comms thread to read last result. */ g_async_queue_push(comm_thread_queue, &go_msg); /* Send stop messages to both threads. */ g_async_queue_push(comm_thread_queue, &stop_msg); g_async_queue_push(exec_thread_queue, &stop_msg); /* Get event wrapper from comms thread. */ evt1 = (CCLEvent*) g_async_queue_pop(host_thread_queue); /* Can't continue until final read is over. */ ccl_event_wait_list_add(&ewl, evt1, NULL); ccl_event_wait(&ewl, &err); HANDLE_ERROR(err); /* Make sure both queues are finished. */ ccl_queue_finish(queue_comm, &err); HANDLE_ERROR(err); ccl_queue_finish(queue_exec, &err); HANDLE_ERROR(err); /* Stop profiling timer and add queues for analysis. */ ccl_prof_stop(prof); ccl_prof_add_queue(prof, "Comms", queue_comm); ccl_prof_add_queue(prof, "Exec", queue_exec); /* Allocate space for base filename. */ filename = (char*) malloc( (strlen(IMAGE_FILE_PREFIX ".png") + IMAGE_FILE_NUM_DIGITS + 1) * sizeof(char)); /* Write results to image files. */ for (cl_uint i = 0; i < CA_ITERS; ++i) { /* Determine next filename. */ sprintf(filename, "%s%0" G_STRINGIFY(IMAGE_FILE_NUM_DIGITS) "d.png", IMAGE_FILE_PREFIX, i); /* Save next image. */ file_write_status = stbi_write_png(filename, CA_WIDTH, CA_HEIGHT, 4, output_images[i], CA_WIDTH * sizeof(cl_uchar4)); /* Give feedback if unable to save image. */ if (!file_write_status) { ERROR_MSG_AND_EXIT("Unable to save image in file."); } } /* Process profiling info. */ ccl_prof_calc(prof, &err); HANDLE_ERROR(err); /* Print profiling info. */ ccl_prof_print_summary(prof); /* Save profiling info. */ ccl_prof_export_info_file(prof, "prof.tsv", &err); HANDLE_ERROR(err); /* Destroy threads. */ g_thread_join(exec_thread); g_thread_join(comm_thread); /* Destroy thread communication queues. */ g_async_queue_unref(comm_thread_queue); g_async_queue_unref(exec_thread_queue); g_async_queue_unref(host_thread_queue); /* Release host buffers. */ free(filename); free(input_image); for (cl_uint i = 0; i < CA_ITERS + 1; ++i) free(output_images[i]); free(output_images); /* Release wrappers. */ ccl_image_destroy(img1); ccl_image_destroy(img2); ccl_program_destroy(prg); ccl_queue_destroy(queue_comm); ccl_queue_destroy(queue_exec); ccl_context_destroy(ctx); /* Destroy profiler. */ ccl_prof_destroy(prof); /* Check all wrappers have been destroyed. */ g_assert(ccl_wrapper_memcheck()); /* Terminate. */ return 0; }
/** * Tests creation (using "simple" constructor), getting info from and * destruction of sampler wrapper objects. * */ static void create_info_destroy_test() { /* Test variables. */ CCLContext* ctx = NULL; CCLSampler* s = NULL; cl_sampler sampler = NULL; GError* err = NULL; cl_int ocl_status; const cl_sampler_properties sampler_properties[] = { CL_SAMPLER_NORMALIZED_COORDS, CL_TRUE, CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE, CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST, 0}; /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Test three ways to create a sampler. */ for (cl_uint i = 0; i < 3; ++i) { /* Create sampler wrapper. */ switch (i) { case 0: /* Create sampler using "simple" constructor. */ s = ccl_sampler_new(ctx, CL_TRUE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &err); g_assert_no_error(err); break; case 1: /* Using the "full" constructor. */ s = ccl_sampler_new_full(ctx, sampler_properties, &err); g_assert_no_error(err); break; case 2: /* Using the "wrap" constructor. */ CCL_BEGIN_IGNORE_DEPRECATIONS sampler = clCreateSampler(ccl_context_unwrap(ctx), CL_TRUE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &ocl_status); g_assert_cmpint(ocl_status, ==, CL_SUCCESS); CCL_END_IGNORE_DEPRECATIONS s = ccl_sampler_new_wrap(sampler); g_assert_cmphex(GPOINTER_TO_UINT(sampler), ==, GPOINTER_TO_UINT(ccl_sampler_unwrap(s))); break; } /* Get some info and check if the return value is as expected. */ cl_addressing_mode am; am = ccl_sampler_get_info_scalar( s, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode, &err); g_assert_no_error(err); g_assert_cmpuint(am, ==, CL_ADDRESS_NONE); cl_filter_mode fm; fm = ccl_sampler_get_info_scalar( s, CL_SAMPLER_FILTER_MODE, cl_filter_mode, &err); g_assert_no_error(err); g_assert_cmpuint(fm, ==, CL_FILTER_NEAREST); cl_bool nc; nc = ccl_sampler_get_info_scalar( s, CL_SAMPLER_NORMALIZED_COORDS, cl_bool, &err); g_assert_no_error(err); g_assert_cmpuint(nc, ==, CL_TRUE); cl_context context; context = ccl_sampler_get_info_scalar( s, CL_SAMPLER_CONTEXT, cl_context, &err); g_assert_no_error(err); g_assert_cmphex(GPOINTER_TO_UINT(context), ==, GPOINTER_TO_UINT(ccl_context_unwrap(ctx))); /* Destroy sampler. */ ccl_sampler_destroy(s); } /* Destroy context. */ ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * Device info main program function. * * @param[in] argc Number of command line arguments. * @param[in] argv Vector of command line arguments. * @return ::CCL_SUCCESS if program returns with no error, or another * ::CCLErrorCode value otherwise. */ int main(int argc, char* argv[]) { /* Error object. */ CCLErr* err = NULL; /* List of platform wrapper objects. */ CCLPlatforms* platforms = NULL; /* List of device wrapper objects. */ CCLDevSelDevices devices = NULL; /* Current platform and device. */ CCLPlatform* p; CCLDevice* d; /* Number of devices in platform. */ guint num_devs; /* Device information value object. */ CCLWrapperInfo* info_value = NULL; /* Device name. */ gchar* dev_name; /* Program return status. */ gint status; /* Parse command line options. */ ccl_devinfo_args_parse(argc, argv, &err); ccl_if_err_goto(err, error_handler); /* If version was requested, output version and exit. */ if (version) { ccl_common_version_print("ccl_devinfo"); exit(0); } /* Check if user requested a list of known information parameters. */ if (opt_list) { /*Yes, user requested list, present it. */ g_fprintf(CCL_DEVINFO_OUT, "\nKnown information parameters:\n\n"); for (gint i = 0; i < ccl_devquery_info_map_size; i++) { if (opt_verb) { g_fprintf(CCL_DEVINFO_OUT, "\t%s\n\t\t%s.\n\n", ccl_devquery_info_map[i].param_name, ccl_devquery_info_map[i].description); } else { g_fprintf(CCL_DEVINFO_OUT, "\t%s\n", ccl_devquery_info_map[i].param_name); } } g_fprintf(CCL_DEVINFO_OUT, "\n"); } else { /* User didn't request list, proceed as normal query. */ /* Ignore platforms and focus only on number of devices in system? */ if (no_platf) { /* Ignore platform, continue device-wise. */ /* Get all devices in the system. */ devices = ccl_devsel_devices_new(&err); ccl_if_err_goto(err, error_handler); /* Cycle through devices. */ for (guint j = 0; j < devices->len; j++) { /* Get out if this device is not to be queried. */ if ((opt_dev != G_MAXUINT) && (j != opt_dev)) continue; /* Get current device. */ d = (CCLDevice*) devices->pdata[j]; /* Get device name. */ info_value = ccl_device_get_info(d, CL_DEVICE_NAME, &err); ccl_if_err_goto(err, error_handler); dev_name = (gchar*) info_value->value; /* Show device information. */ g_fprintf(CCL_DEVINFO_OUT, "\n [ Device #%d: %s ]\n\n", j, dev_name); ccl_devinfo_show_device_info(d); } g_fprintf(CCL_DEVINFO_OUT, "\n"); } else { /* Do not ignore platforms, continue platform-wise. */ /* Get list of platform wrapper objects. */ platforms = ccl_platforms_new(&err); ccl_if_err_goto(err, error_handler); /* Cycle through platforms. */ for (guint i = 0; i < ccl_platforms_count(platforms); i++) { /* Get out if this platform is not to be queried. */ if ((opt_platf != G_MAXUINT) && (i != opt_platf)) continue; /* Get current platform. */ p = ccl_platforms_get(platforms, i); /* Show platform information. */ ccl_devinfo_show_platform_info(p, i); /* Get number of devices. */ num_devs = ccl_platform_get_num_devices(p, &err); /* Is this a platform without devices? */ if ((err) && (err->domain == CCL_OCL_ERROR) && (err->code == CL_DEVICE_NOT_FOUND)) { /* Clear "device not found" error. */ g_clear_error(&err); /* Inform about non-existing devices. */ g_fprintf(CCL_DEVINFO_OUT, "\n [ No devices found ]\n\n"); /* Skip this platform. */ continue; } ccl_if_err_goto(err, error_handler); /* Cycle through devices. */ for (guint j = 0; j < num_devs; j++) { /* Get out if this device is not to be queried. */ if ((opt_dev != G_MAXUINT) && (j != opt_dev)) continue; /* Get current device. */ d = ccl_platform_get_device(p, j, &err); ccl_if_err_goto(err, error_handler); /* Get device name. */ info_value = ccl_device_get_info(d, CL_DEVICE_NAME, &err); ccl_if_err_goto(err, error_handler); dev_name = (gchar*) info_value->value; /* Show device information. */ g_fprintf(CCL_DEVINFO_OUT, "\n [ Device #%d: %s ]\n\n", j, dev_name); ccl_devinfo_show_device_info(d); } g_fprintf(CCL_DEVINFO_OUT, "\n"); } } } /* If we got here, everything is OK. */ g_assert(err == NULL); status = CCL_SUCCESS; goto cleanup; error_handler: /* If we got here there was an error, verify that it is so. */ g_assert(err != NULL); g_fprintf(stderr, "%s\n", err->message); status = (err->domain == CCL_ERROR) ? err->code : CCL_ERROR_OTHER; g_error_free(err); cleanup: /* Free stuff! */ if (platforms) ccl_platforms_destroy(platforms); if (devices) ccl_devsel_devices_destroy(devices); g_strfreev(opt_custom); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_return_val_if_fail(ccl_wrapper_memcheck(), CCL_ERROR_OTHER); /* Return status. */ return status; }
/** * Canonical example main function. * */ int main(int argc, char** argv) { /* Number of elements in buffer. */ size_t buf_n = DEF_BUF_N; /* Device selected specified in the command line. */ int dev_idx = -1; /* Program return value. */ int ret_val; /* Check if a device was specified in the command line. */ if (argc >= 2) { dev_idx = atoi(argv[1]); } /* Check if a new buffer size was specified in the command line. */ if (argc >= 3) { buf_n = atoi(argv[2]); } /* Wrappers. */ CCLContext* ctx = NULL; CCLProgram* prg = NULL; CCLDevice* dev = NULL; CCLQueue* queue = NULL; CCLKernel* krnl = NULL; CCLBuffer* a_dev; CCLBuffer* b_dev; CCLBuffer* c_dev; CCLEvent* evt_write1; CCLEvent* evt_write2; CCLEvent* evt_exec; CCLEventWaitList ewl = NULL; /* Profiler. */ CCLProf* prof; /* Global and local worksizes. */ size_t gws = 0; size_t lws = 0; /* Host buffers. */ cl_uint* a_host = NULL; cl_uint* b_host = NULL; cl_uint* c_host = NULL; cl_uint d_host; /* Error reporting object. */ CCLErr* err = NULL; /* Check results flag. */ cl_bool check_result; /* Create a context with device selected from menu. */ ctx = ccl_context_new_from_menu_full(&dev_idx, &err); HANDLE_ERROR(err); /* Get the selected device. */ dev = ccl_context_get_device(ctx, 0, &err); HANDLE_ERROR(err); /* Create a new program from kernel source. */ prg = ccl_program_new_from_source(ctx, KERNEL_SRC, &err); HANDLE_ERROR(err); /* Build program. */ ccl_program_build(prg, NULL, &err); HANDLE_ERROR(err); /* Create a command queue. */ queue = ccl_queue_new(ctx, dev, CL_QUEUE_PROFILING_ENABLE, &err); HANDLE_ERROR(err); /* Get kernel object. */ krnl = ccl_program_get_kernel(prg, KERNEL_NAME, &err); HANDLE_ERROR(err); /* Get worksizes. */ lws = ccl_kernel_suggest_worksizes(krnl, dev, 1, &buf_n, &gws, &lws, &err); HANDLE_ERROR(err); /* Show worksizes. */ printf("\n"); printf(" * Global worksize: %d\n", (int) gws); printf(" * Local worksize : %d\n", (int) lws); /* Initialize host buffers. */ a_host = (cl_uint*) malloc(sizeof(cl_uint) * buf_n); b_host = (cl_uint*) malloc(sizeof(cl_uint) * buf_n); c_host = (cl_uint*) malloc(sizeof(cl_uint) * buf_n); /* Fill host buffers. */ for (cl_uint i = 0; i < buf_n; ++i) { a_host[i] = i; b_host[i] = buf_n - i; } d_host = buf_n / 4; /* Create device buffers. */ a_dev = ccl_buffer_new(ctx, CL_MEM_READ_ONLY, buf_n * sizeof(cl_uint), NULL, &err); HANDLE_ERROR(err); b_dev = ccl_buffer_new(ctx, CL_MEM_READ_ONLY, buf_n * sizeof(cl_uint), NULL, &err); HANDLE_ERROR(err); c_dev = ccl_buffer_new(ctx, CL_MEM_WRITE_ONLY, buf_n * sizeof(cl_uint), NULL, &err); HANDLE_ERROR(err); /* Copy host data to device buffers without waiting for transfer * to terminate before continuing host program. */ evt_write1 = ccl_buffer_enqueue_write(a_dev, queue, CL_FALSE, 0, buf_n * sizeof(cl_uint), a_host, NULL, &err); HANDLE_ERROR(err); evt_write2 = ccl_buffer_enqueue_write(b_dev, queue, CL_FALSE, 0, buf_n * sizeof(cl_uint), b_host, NULL, &err); HANDLE_ERROR(err); /* Initialize event wait list and add the two transfer events. */ ccl_event_wait_list_add(&ewl, evt_write1, evt_write2, NULL); /* Execute program kernel, waiting for the two transfer events * to terminate (this will empty the event wait list). */ evt_exec = ccl_program_enqueue_kernel(prg, KERNEL_NAME, queue, 1, NULL, &gws, &lws, &ewl, &err, /* Kernel arguments. */ a_dev, b_dev, c_dev, ccl_arg_priv(d_host, cl_uint), ccl_arg_priv(buf_n, cl_uint), NULL); HANDLE_ERROR(err); /* Add the kernel termination event to the wait list. */ ccl_event_wait_list_add(&ewl, evt_exec, NULL); /* Sync. queue for events in wait list (just the execute event in * this case) to terminate before going forward... */ ccl_enqueue_barrier(queue, &ewl, &err); HANDLE_ERROR(err); /* Read back results from host waiting for transfer to terminate * before continuing host program. */ ccl_buffer_enqueue_read(c_dev, queue, CL_TRUE, 0, buf_n * sizeof(cl_uint), c_host, NULL, &err); HANDLE_ERROR(err); /* Check results are as expected (not available with OpenCL stub). */ check_result = CL_TRUE; for (cl_uint i = 0; i < buf_n; ++i) { if(c_host[i] != a_host[i] + b_host[i] + d_host) { check_result = CL_FALSE; break; } } if (check_result) { fprintf(stdout, " * Kernel execution produced the expected results.\n"); ret_val = EXIT_SUCCESS; } else { fprintf(stderr, " * Kernel execution failed to produce the expected results.\n"); ret_val = EXIT_FAILURE; } /* Perform profiling. */ prof = ccl_prof_new(); ccl_prof_add_queue(prof, "queue1", queue); ccl_prof_calc(prof, &err); HANDLE_ERROR(err); /* Show profiling info. */ ccl_prof_print_summary(prof); /* Export profiling info. */ ccl_prof_export_info_file(prof, "out.tsv", &err); HANDLE_ERROR(err); /* Destroy profiler object. */ ccl_prof_destroy(prof); /* Destroy host buffers. */ free(a_host); free(b_host); free(c_host); /* Destroy wrappers. */ ccl_buffer_destroy(a_dev); ccl_buffer_destroy(b_dev); ccl_buffer_destroy(c_dev); ccl_queue_destroy(queue); ccl_program_destroy(prg); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly freed. */ assert(ccl_wrapper_memcheck()); /* Bye. */ return ret_val; }