Merge pull request #1756 from alalek:ocl_workaround_memory_leaks_with_subbuffer
authorAndrey Pavlenko <andrey.pavlenko@itseez.com>
Wed, 6 Nov 2013 14:26:39 +0000 (18:26 +0400)
committerOpenCV Buildbot <buildbot@opencv.org>
Wed, 6 Nov 2013 14:26:39 +0000 (18:26 +0400)
modules/ocl/src/cl_operations.cpp

index d96f347..7ed1a79 100644 (file)
@@ -148,35 +148,52 @@ void openCLMallocPitchEx(Context *ctx, void **dev_ptr, size_t *pitch,
 {
     cl_int status;
     size_t size = widthInBytes * height;
+    bool useSubBuffers =
 #ifndef MEMORY_CORRUPTION_GUARD
-    *dev_ptr = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
-                              size, 0, &status);
-    openCLVerifyCall(status);
+            false;
 #else
-    size_t allocSize = size + __memory_corruption_guard_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_guard_bytes, size};
-    *dev_ptr =  clCreateSubBuffer(mainBuffer,
-            gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
-            CL_BUFFER_CREATE_TYPE_REGION, &r,
-            &status);
-    openCLVerifyCall(status);
+            true;
+#endif
+    const DeviceInfo& devInfo = ctx->getDeviceInfo();
+    if (useSubBuffers && devInfo.isIntelDevice)
+    {
+        useSubBuffers = false; // TODO FIXIT We observe memory leaks then we working with sub-buffers
+                               // on the CPU device of Intel OpenCL SDK (Linux). We will investigate this later.
+    }
+    if (!useSubBuffers)
+    {
+        *dev_ptr = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
+                                  size, 0, &status);
+        openCLVerifyCall(status);
+    }
+#ifdef MEMORY_CORRUPTION_GUARD
+    else
+    {
+        size_t allocSize = size + __memory_corruption_guard_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_guard_bytes, size};
+        *dev_ptr = clCreateSubBuffer(mainBuffer,
+                gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
+                CL_BUFFER_CREATE_TYPE_REGION, &r,
+                &status);
+        openCLVerifyCall(status);
 #ifdef CHECK_MEMORY_CORRUPTION
-    std::vector<int> tmp(__memory_corruption_guard_bytes / sizeof(int),
-            __memory_corruption_check_pattern);
-    CV_Assert(tmp.size() * sizeof(int) == __memory_corruption_guard_bytes);
-    openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx),
-            mainBuffer, CL_FALSE, 0, __memory_corruption_guard_bytes, &tmp[0],
-            0, NULL, NULL));
-    openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx),
-            mainBuffer, CL_FALSE, __memory_corruption_guard_bytes + size, __memory_corruption_guard_bytes, &tmp[0],
-            0, NULL, NULL));
-    clFinish(getClCommandQueue(ctx));
+        std::vector<int> tmp(__memory_corruption_guard_bytes / sizeof(int),
+                __memory_corruption_check_pattern);
+        CV_Assert(tmp.size() * sizeof(int) == __memory_corruption_guard_bytes);
+        openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx),
+                mainBuffer, CL_FALSE, 0, __memory_corruption_guard_bytes, &tmp[0],
+                0, NULL, NULL));
+        openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx),
+                mainBuffer, CL_FALSE, __memory_corruption_guard_bytes + size, __memory_corruption_guard_bytes, &tmp[0],
+                0, NULL, NULL));
+        clFinish(getClCommandQueue(ctx));
 #endif
-    CheckBuffers data(mainBuffer, size, widthInBytes, height);
-    __check_buffers.insert(std::pair<cl_mem, CheckBuffers>((cl_mem)*dev_ptr, data));
+        CheckBuffers data(mainBuffer, size, widthInBytes, height);
+        __check_buffers.insert(std::pair<cl_mem, CheckBuffers>((cl_mem)*dev_ptr, data));
+    }
 #endif
     *pitch = widthInBytes;
 }
@@ -230,6 +247,7 @@ void openCLCopyBuffer2D(Context *ctx, void *dst, size_t dpitch, int dst_offset,
 
 void openCLFree(void *devPtr)
 {
+    openCLSafeCall(clReleaseMemObject((cl_mem)devPtr));
 #ifdef MEMORY_CORRUPTION_GUARD
 #ifdef CHECK_MEMORY_CORRUPTION
     bool failBefore = false, failAfter = false;
@@ -270,9 +288,7 @@ void openCLFree(void *devPtr)
         openCLSafeCall(clReleaseMemObject(data.mainBuffer));
         __check_buffers.erase(i);
     }
-#endif
-    openCLSafeCall(clReleaseMemObject((cl_mem)devPtr));
-#if defined(MEMORY_CORRUPTION_GUARD) && defined(CHECK_MEMORY_CORRUPTION)
+#if defined(CHECK_MEMORY_CORRUPTION)
     if (failBefore)
     {
 #ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR
@@ -291,7 +307,8 @@ void openCLFree(void *devPtr)
         CV_Error(CV_StsInternal, "Memory corruption detected: after buffer");
 #endif
     }
-#endif
+#endif // CHECK_MEMORY_CORRUPTION
+#endif // MEMORY_CORRUPTION_GUARD
 }
 
 cl_kernel openCLGetKernelFromSource(const Context *ctx, const cv::ocl::ProgramEntry* source, string kernelName)