diff --git a/test_conformance/basic/test_bufferreadwriterect.cpp b/test_conformance/basic/test_bufferreadwriterect.cpp index 03ba27061b..82055adfca 100644 --- a/test_conformance/basic/test_bufferreadwriterect.cpp +++ b/test_conformance/basic/test_bufferreadwriterect.cpp @@ -26,15 +26,19 @@ #include "testBase.h" -#define CL_EXIT_ERROR(cmd,format,...) \ -{ \ -if ((cmd) != CL_SUCCESS) { \ -log_error("CL ERROR: %s %u: ", __FILE__,__LINE__); \ -log_error(format,## __VA_ARGS__ ); \ -log_error("\n"); \ -/*abort();*/ \ -} \ -} +#define TEST_READWRITERECT_PRINT_BUFFER 0 +#define CL_EXIT_ERROR(cmd, format, ...) \ + { \ + if ((cmd) != CL_SUCCESS) \ + { \ + log_error("CL ERROR: %s %u: ", __FILE__, __LINE__); \ + log_error(format, ##__VA_ARGS__); \ + log_error("\n"); \ + /*abort();*/ \ + } \ + } + +namespace { typedef unsigned char BufferType; @@ -48,12 +52,11 @@ size_t height [TotalImages]; size_t depth [TotalImages]; // cl buffer and host buffer. -cl_mem buffer [TotalImages]; -BufferType* verify[TotalImages]; -BufferType* backing[TotalImages]; +clMemWrapper buffer[TotalImages]; +std::vector verify[TotalImages]; // Temporary buffer used for read and write operations. -BufferType* tmp_buffer; +std::vector tmp_buffer; size_t tmp_buffer_size; size_t num_tries = 50; // Number of randomly selected operations to perform. @@ -61,7 +64,7 @@ size_t alloc_scale = 2; // Scale term applied buffer allocation size. MTdata mt; // Initialize a buffer in host memory containing random values of the specified size. -static void initialize_image(BufferType* ptr, size_t w, size_t h, size_t d, MTdata mt) +void initialize_image(BufferType* ptr, size_t w, size_t h, size_t d, MTdata mt) { enum { ElementSize = sizeof(BufferType)/sizeof(unsigned char) }; @@ -73,6 +76,7 @@ static void initialize_image(BufferType* ptr, size_t w, size_t h, size_t d, MTda } } +#if TEST_READWRITERECT_PRINT_BUFFER // This function prints the contents of a buffer to standard error. void print_buffer(BufferType* buf, size_t w, size_t h, size_t d) { log_error("Size = %zux%zux%zu (%zu total)\n", w, h, d, w * h * d); @@ -87,50 +91,73 @@ void print_buffer(BufferType* buf, size_t w, size_t h, size_t d) { log_error("\n"); } } +#endif // Returns true if the two specified regions overlap. -bool check_overlap_rect(size_t src_offset[3], - size_t dst_offset[3], - size_t region[3], - size_t row_pitch, - size_t slice_pitch) +bool check_overlap_rect(size_t src_offset[3], size_t dst_offset[3], + size_t region[3], size_t src) { + // Copy between cl buffers. + size_t slice_pitch = + (width[src] * height[src] != 1) ? width[src] * height[src] : 0; + size_t row_pitch = width[src]; + const size_t src_min[] = { src_offset[0], src_offset[1], src_offset[2] }; - const size_t src_max[] = { src_offset[0] + region[0], src_offset[1] + region[1], src_offset[2] + region[2] }; + const size_t src_max[] = { src_offset[0] + region[0], + src_offset[1] + region[1], + src_offset[2] + region[2] }; const size_t dst_min[] = { dst_offset[0], dst_offset[1], dst_offset[2] }; const size_t dst_max[] = { dst_offset[0] + region[0], dst_offset[1] + region[1], - dst_offset[2] + region[2]}; -// Check for overlap - bool overlap = true; - unsigned i; - for (i = 0; i != 3; ++i) - { - overlap = overlap && (src_min[i] < dst_max[i]) && (src_max[i] > dst_min[i]); - } + dst_offset[2] + region[2] }; + // Check for overlap + bool overlap = true; + unsigned i; + for (i = 0; i != 3; ++i) + { + overlap = + overlap && (src_min[i] < dst_max[i]) && (src_max[i] > dst_min[i]); + } - size_t dst_start = dst_offset[2] * slice_pitch + dst_offset[1] * row_pitch + dst_offset[0]; - size_t dst_end = dst_start + (region[2] * slice_pitch + - region[1] * row_pitch + region[0]); - size_t src_start = src_offset[2] * slice_pitch + src_offset[1] * row_pitch + src_offset[0]; - size_t src_end = src_start + (region[2] * slice_pitch + - region[1] * row_pitch + region[0]); - if (!overlap) { - size_t delta_src_x = (src_offset[0] + region[0] > row_pitch) ? - src_offset[0] + region[0] - row_pitch : 0; size_t delta_dst_x = (dst_offset[0] + region[0] > row_pitch) ? - dst_offset[0] + region[0] - row_pitch : 0; - if ((delta_src_x > 0 && delta_src_x > dst_offset[0]) || - (delta_dst_x > 0 && delta_dst_x > src_offset[0])) { - if ((src_start <= dst_start && dst_start < src_end) || (dst_start <= src_start && src_start < dst_end)) overlap = true; + size_t dst_start = + dst_offset[2] * slice_pitch + dst_offset[1] * row_pitch + dst_offset[0]; + size_t dst_end = dst_start + + (region[2] * slice_pitch + region[1] * row_pitch + region[0]); + size_t src_start = + src_offset[2] * slice_pitch + src_offset[1] * row_pitch + src_offset[0]; + size_t src_end = src_start + + (region[2] * slice_pitch + region[1] * row_pitch + region[0]); + if (!overlap) + { + size_t delta_src_x = (src_offset[0] + region[0] > row_pitch) + ? src_offset[0] + region[0] - row_pitch + : 0; + size_t delta_dst_x = (dst_offset[0] + region[0] > row_pitch) + ? dst_offset[0] + region[0] - row_pitch + : 0; + if ((delta_src_x > 0 && delta_src_x > dst_offset[0]) + || (delta_dst_x > 0 && delta_dst_x > src_offset[0])) + { + if ((src_start <= dst_start && dst_start < src_end) + || (dst_start <= src_start && src_start < dst_end)) + overlap = true; } - if (region[2] > 1) { - size_t src_height = slice_pitch / row_pitch; size_t dst_height = slice_pitch / row_pitch; - size_t delta_src_y = (src_offset[1] + region[1] > src_height) ? src_offset[1] + region[1] - src_height : 0; - size_t delta_dst_y = (dst_offset[1] + region[1] > dst_height) ? dst_offset[1] + region[1] - dst_height : 0; - if ((delta_src_y > 0 && delta_src_y > dst_offset[1]) || - (delta_dst_y > 0 && delta_dst_y > src_offset[1])) { - if ((src_start <= dst_start && dst_start < src_end) || (dst_start <= src_start && src_start < dst_end)) + if (region[2] > 1) + { + size_t src_height = slice_pitch / row_pitch; + size_t dst_height = slice_pitch / row_pitch; + size_t delta_src_y = (src_offset[1] + region[1] > src_height) + ? src_offset[1] + region[1] - src_height + : 0; + size_t delta_dst_y = (dst_offset[1] + region[1] > dst_height) + ? dst_offset[1] + region[1] - dst_height + : 0; + if ((delta_src_y > 0 && delta_src_y > dst_offset[1]) + || (delta_dst_y > 0 && delta_dst_y > src_offset[1])) + { + if ((src_start <= dst_start && dst_start < src_end) + || (dst_start <= src_start && src_start < dst_end)) overlap = true; } } @@ -138,40 +165,59 @@ bool check_overlap_rect(size_t src_offset[3], return overlap; } - - // This function invokes the CopyBufferRect CL command and then mirrors the operation on the host side verify buffers. -int copy_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { +int copy_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, + size_t doffset[3], size_t dregion[3]) +{ + // Copy between cl buffers + // Compute or provide zero pitches randomly + size_t src_slice_pitch = + (width[src] * height[src] != 1 && ((genrand_int32(mt) % 2) != 0)) + ? width[src] * height[src] + : 0; + size_t dst_slice_pitch = + (width[dst] * height[dst] != 1 && ((genrand_int32(mt) % 2) != 0)) + ? width[dst] * height[dst] + : 0; + size_t src_row_pitch = ((genrand_int32(mt) % 2) != 0) ? width[src] : 0; + size_t dst_row_pitch = ((genrand_int32(mt) % 2) != 0) ? width[dst] : 0; - // Copy between cl buffers. - size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; - size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; - size_t src_row_pitch = width[src]; + if (src == dst) + { + src_row_pitch = dst_row_pitch; + src_slice_pitch = dst_slice_pitch; + } cl_int err; - if (check_overlap_rect(soffset,doffset,sregion,src_row_pitch, src_slice_pitch)) { - log_info( "Copy overlap reported, skipping copy buffer rect\n" ); + if (check_overlap_rect(soffset, doffset, sregion, src)) + { + log_info("Copy overlap reported, skipping copy buffer rect\n"); return CL_SUCCESS; - } else { + } + else + { if ((err = clEnqueueCopyBufferRect( gQueue, buffer[src], buffer[dst], soffset, doffset, sregion, /*dregion,*/ - width[src], src_slice_pitch, width[dst], dst_slice_pitch, 0, - NULL, NULL)) + src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, + 0, NULL, NULL)) != CL_SUCCESS) { - CL_EXIT_ERROR(err, "clEnqueueCopyBufferRect failed between %u and %u",(unsigned)src,(unsigned)dst); + CL_EXIT_ERROR(err, + "clEnqueueCopyBufferRect failed between %u and %u", + (unsigned)src, (unsigned)dst); } } // Copy between host buffers. size_t total = sregion[0] * sregion[1] * sregion[2]; - size_t spitch = width[src]; - size_t sslice = width[src]*height[src]; - - size_t dpitch = width[dst]; - size_t dslice = width[dst]*height[dst]; + size_t spitch = (src_row_pitch == 0) ? sregion[0] : src_row_pitch; + size_t sslice = + (src_slice_pitch == 0) ? sregion[1] * spitch : src_slice_pitch; + size_t dpitch = (dst_row_pitch == 0) ? sregion[0] : dst_row_pitch; + size_t dslice = + (dst_slice_pitch == 0) ? sregion[1] * dpitch : dst_slice_pitch; for (size_t i = 0; i != total; ++i) { @@ -204,11 +250,9 @@ int immutable_copy_region(size_t src, size_t soffset[3], size_t sregion[3], (width[src] * height[src] != 1) ? width[src] * height[src] : 0; size_t dst_slice_pitch = (width[dst] * height[dst] != 1) ? width[dst] * height[dst] : 0; - size_t src_row_pitch = width[src]; cl_int err; - if (check_overlap_rect(soffset, doffset, sregion, src_row_pitch, - src_slice_pitch)) + if (check_overlap_rect(soffset, doffset, sregion, src)) { log_info("Copy overlap reported, skipping copy buffer rect\n"); return CL_SUCCESS; @@ -261,7 +305,7 @@ int verify_region(BufferType* device, size_t src, size_t soffset[3], size_t sreg "%zu) of region\n", i, sx, sy, sz); log_error("0x%02x != 0x%02x\n", device[d_idx], verify[src][s_idx]); -#if 0 +#if TEST_READWRITERECT_PRINT_BUFFER // Uncomment this section to print buffers. log_error("Device (copy): [%lu]\n",dst); print_buffer(device,width[dst],height[dst],depth[dst]); @@ -278,7 +322,6 @@ int verify_region(BufferType* device, size_t src, size_t soffset[3], size_t sreg return 0; } - // This function invokes ReadBufferRect to read a region from the // specified source buffer into a temporary destination buffer. The // contents of the temporary buffer are then compared to the source @@ -286,7 +329,7 @@ int verify_region(BufferType* device, size_t src, size_t soffset[3], size_t sreg int read_verify_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { // Clear the temporary destination host buffer. - memset(tmp_buffer, 0xff, tmp_buffer_size); + memset(tmp_buffer.data(), 0xff, tmp_buffer_size * sizeof(BufferType)); size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; @@ -295,11 +338,12 @@ int read_verify_region(size_t src, size_t soffset[3], size_t sregion[3], size_t CL_EXIT_ERROR(clEnqueueReadBufferRect( gQueue, buffer[src], CL_TRUE, soffset, doffset, sregion, width[src], src_slice_pitch, width[dst], dst_slice_pitch, - tmp_buffer, 0, NULL, NULL), + tmp_buffer.data(), 0, NULL, NULL), "clEnqueueCopyBufferRect failed between %u and %u", (unsigned)src, (unsigned)dst); - return verify_region(tmp_buffer,src,soffset,sregion,dst,doffset); + return verify_region(tmp_buffer.data(), src, soffset, sregion, dst, + doffset); } // This function performs the same verification check as @@ -333,19 +377,20 @@ int map_verify_region(size_t src) { // region of it to a region in the specified destination buffer. int write_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { - initialize_image(tmp_buffer, tmp_buffer_size, 1, 1, mt); + initialize_image(tmp_buffer.data(), tmp_buffer_size, 1, 1, mt); // memset(tmp_buffer, 0xf0, tmp_buffer_size); size_t src_slice_pitch = (width[src]*height[src] != 1) ? width[src]*height[src] : 0; size_t dst_slice_pitch = (width[dst]*height[dst] != 1) ? width[dst]*height[dst] : 0; // Copy the source region of the cl buffer, to the destination region of the temporary buffer. - CL_EXIT_ERROR(clEnqueueWriteBufferRect( - gQueue, buffer[dst], CL_TRUE, doffset, soffset, - /*sregion,*/ dregion, width[dst], dst_slice_pitch, - width[src], src_slice_pitch, tmp_buffer, 0, NULL, NULL), - "clEnqueueWriteBufferRect failed between %u and %u", - (unsigned)src, (unsigned)dst); + CL_EXIT_ERROR( + clEnqueueWriteBufferRect(gQueue, buffer[dst], CL_TRUE, doffset, soffset, + /*sregion,*/ dregion, width[dst], + dst_slice_pitch, width[src], src_slice_pitch, + tmp_buffer.data(), 0, NULL, NULL), + "clEnqueueWriteBufferRect failed between %u and %u", (unsigned)src, + (unsigned)dst); // Copy from the temporary buffer to the host buffer. size_t spitch = width[src]; @@ -378,7 +423,7 @@ int write_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, s int immutable_write_region(size_t src, size_t soffset[3], size_t sregion[3], size_t dst, size_t doffset[3], size_t dregion[3]) { - initialize_image(tmp_buffer, tmp_buffer_size, 1, 1, mt); + initialize_image(tmp_buffer.data(), tmp_buffer_size, 1, 1, mt); size_t src_slice_pitch = (width[src] * height[src] != 1) ? width[src] * height[src] : 0; @@ -387,8 +432,8 @@ int immutable_write_region(size_t src, size_t soffset[3], size_t sregion[3], cl_int error = clEnqueueWriteBufferRect( gQueue, buffer[dst], CL_TRUE, doffset, soffset, dregion, width[dst], - dst_slice_pitch, width[src], src_slice_pitch, tmp_buffer, 0, nullptr, - nullptr); + dst_slice_pitch, width[src], src_slice_pitch, tmp_buffer.data(), 0, + nullptr, nullptr); if (error != CL_INVALID_OPERATION) { @@ -401,11 +446,6 @@ int immutable_write_region(size_t src, size_t soffset[3], size_t sregion[3], return TEST_PASS; } -void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data ) -{ - free( data ); -} - using test_fn = int (*)(size_t, size_t[3], size_t[3], size_t, size_t[3], size_t[3]); struct TestFunctions @@ -415,12 +455,10 @@ struct TestFunctions test_fn write; }; -static int test_bufferreadwriterect_impl(cl_device_id device, - cl_context context, - cl_command_queue queue, - int num_elements, - cl_map_flags buffer_flags, - const TestFunctions& test_functions) +int test_bufferreadwriterect_impl(cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements, + cl_map_flags buffer_flags, + const TestFunctions& test_functions) { gQueue = queue; cl_int err; @@ -487,37 +525,28 @@ static int test_bufferreadwriterect_impl(cl_device_id device, // Allocate a temporary buffer for read and write operations. tmp_buffer_size = max_size; - tmp_buffer = (BufferType*)malloc(tmp_buffer_size); + tmp_buffer.resize(tmp_buffer_size, 0); // Initialize cl buffers log_info( "Initializing buffers\n" ); for (unsigned i=0; i != TotalImages; ++i) { - size_t size_bytes = width[i]*height[i]*depth[i]*sizeof(BufferType); + size_t num_elems = width[i] * height[i] * depth[i]; + size_t size_bytes = num_elems * sizeof(BufferType); // Allocate a host copy of the buffer for verification. - verify[i] = (BufferType*)malloc(size_bytes); - CL_EXIT_ERROR(verify[i] ? CL_SUCCESS : -1, "malloc of host buffer failed for buffer %u", i); - - // Allocate the buffer in host memory. - backing[i] = (BufferType*)malloc(size_bytes); - CL_EXIT_ERROR(backing[i] ? CL_SUCCESS : -1, "malloc of backing buffer failed for buffer %u", i); + verify[i].resize(num_elems); + CL_EXIT_ERROR(verify[i].data() ? CL_SUCCESS : -1, + "malloc of host buffer failed for buffer %u", i); // Generate a random buffer. log_info( "Initializing buffer %u\n", i ); - initialize_image(verify[i], width[i], height[i], depth[i], mt); - - // Copy the image into a buffer which will passed to CL. - memcpy(backing[i], verify[i], size_bytes); + initialize_image(verify[i].data(), width[i], height[i], depth[i], mt); // Create the CL buffer. - buffer[i] = - clCreateBuffer(context, buffer_flags, size_bytes, backing[i], &err); - CL_EXIT_ERROR(err,"clCreateBuffer failed for buffer %u", i); - - // Make sure buffer is cleaned up appropriately if we encounter an error in the rest of the calls. - err = clSetMemObjectDestructorCallback( buffer[i], mem_obj_destructor_callback, backing[i] ); - CL_EXIT_ERROR(err, "Unable to set mem object destructor callback" ); + buffer[i] = clCreateBuffer(context, buffer_flags, size_bytes, + verify[i].data(), &err); + CL_EXIT_ERROR(err, "clCreateBuffer failed for buffer %u", i); } // Main test loop, run num_tries times. @@ -631,11 +660,6 @@ static int test_bufferreadwriterect_impl(cl_device_id device, // Clean-up. free_mtdata(mt); - for (unsigned i=0;i