diff --git a/modules/ocl/src/cl_operations.cpp b/modules/ocl/src/cl_operations.cpp index cd948fc9d5..7f09b1e505 100644 --- a/modules/ocl/src/cl_operations.cpp +++ b/modules/ocl/src/cl_operations.cpp @@ -109,6 +109,31 @@ cl_mem openCLCreateBuffer(Context *ctx, size_t flag , size_t size) return buffer; } +//#define CHECK_MEMORY_CORRUPTION +#ifdef CHECK_MEMORY_CORRUPTION +//#define CHECK_MEMORY_CORRUPTION_PRINT_ERROR +#define CHECK_MEMORY_CORRUPTION_RAISE_ERROR +static const int __memory_corruption_check_bytes = 1024*1024; +static const int __memory_corruption_check_pattern = 0x14326547; // change pattern for sizeof(int)==8 +struct CheckBuffers +{ + cl_mem mainBuffer; + size_t size; + size_t widthInBytes, height; + CheckBuffers() + : mainBuffer(NULL), size(0), widthInBytes(0), height(0) + { + // nothing + } + CheckBuffers(cl_mem _mainBuffer, size_t _size, size_t _widthInBytes, size_t _height) + : mainBuffer(_mainBuffer), size(_size), widthInBytes(_widthInBytes), height(_height) + { + // notihng + } +}; +static std::map __check_buffers; +#endif + void openCLMallocPitch(Context *ctx, void **dev_ptr, size_t *pitch, size_t widthInBytes, size_t height) { @@ -119,9 +144,34 @@ void openCLMallocPitchEx(Context *ctx, void **dev_ptr, size_t *pitch, size_t widthInBytes, size_t height, DevMemRW rw_type, DevMemType mem_type) { cl_int status; + size_t size = widthInBytes * height; +#ifndef CHECK_MEMORY_CORRUPTION *dev_ptr = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type], - widthInBytes * height, 0, &status); + size, 0, &status); openCLVerifyCall(status); +#else + size_t allocSize = size + __memory_corruption_check_bytes * 2; + cl_mem mainBuffer = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type], + allocSize, 0, &status); + openCLVerifyCall(status); + cl_buffer_region r = {__memory_corruption_check_bytes, size}; + *dev_ptr = clCreateSubBuffer(mainBuffer, + gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type], + CL_BUFFER_CREATE_TYPE_REGION, &r, + &status); + openCLVerifyCall(status); + std::vector tmp(__memory_corruption_check_bytes / sizeof(int), + __memory_corruption_check_pattern); + CV_Assert(tmp.size() * sizeof(int) == __memory_corruption_check_bytes); + openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx), + mainBuffer, CL_TRUE, 0, __memory_corruption_check_bytes, &tmp[0], + 0, NULL, NULL)); + openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx), + mainBuffer, CL_TRUE, __memory_corruption_check_bytes + size, __memory_corruption_check_bytes, &tmp[0], + 0, NULL, NULL)); + CheckBuffers data(mainBuffer, size, widthInBytes, height); + __check_buffers.insert(std::pair((cl_mem)*dev_ptr, data)); +#endif *pitch = widthInBytes; } @@ -174,7 +224,59 @@ void openCLCopyBuffer2D(Context *ctx, void *dst, size_t dpitch, int dst_offset, void openCLFree(void *devPtr) { +#ifdef CHECK_MEMORY_CORRUPTION + bool failBefore = false, failAfter = false; + CheckBuffers data; + std::map::iterator i = __check_buffers.find((cl_mem)devPtr); + if (i != __check_buffers.end()) + { + data = i->second; + Context* ctx = Context::getContext(); + std::vector checkBefore(__memory_corruption_check_bytes); + std::vector checkAfter(__memory_corruption_check_bytes); + openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(ctx), + data.mainBuffer, CL_TRUE, 0, __memory_corruption_check_bytes, &checkBefore[0], + 0, NULL, NULL)); + openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(ctx), + data.mainBuffer, CL_TRUE, __memory_corruption_check_bytes + data.size, __memory_corruption_check_bytes, &checkAfter[0], + 0, NULL, NULL)); + + std::vector tmp(__memory_corruption_check_bytes / sizeof(int), + __memory_corruption_check_pattern); + + if (memcmp(&checkBefore[0], &tmp[0], __memory_corruption_check_bytes) != 0) + { + failBefore = true; + } + if (memcmp(&checkAfter[0], &tmp[0], __memory_corruption_check_bytes) != 0) + { + failAfter = true; + } + openCLSafeCall(clReleaseMemObject(data.mainBuffer)); + __check_buffers.erase(i); + } +#endif openCLSafeCall(clReleaseMemObject((cl_mem)devPtr)); +#ifdef CHECK_MEMORY_CORRUPTION + if (failBefore) + { +#ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR + std::cerr << "ERROR: Memory corruption detected: before buffer: " << cv::format("widthInBytes=%d height=%d", (int)data.widthInBytes, (int)data.height) << std::endl; +#endif +#ifdef CHECK_MEMORY_CORRUPTION_RAISE_ERROR + CV_Error(CV_StsInternal, "Memory corruption detected: before buffer"); +#endif + } + if (failAfter) + { +#ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR + std::cerr << "ERROR: Memory corruption detected: after buffer: " << cv::format("widthInBytes=%d height=%d", (int)data.widthInBytes, (int)data.height) << std::endl; +#endif +#ifdef CHECK_MEMORY_CORRUPTION_RAISE_ERROR + CV_Error(CV_StsInternal, "Memory corruption detected: after buffer"); +#endif + } +#endif } cl_kernel openCLGetKernelFromSource(const Context *ctx, const cv::ocl::ProgramEntry* source, string kernelName)