Repository: opencv
Issue: `Mat::getUMat()` moves data, therefore invalidating pointers within OpenCL SVM data
Labels: category: core,category: ocl,category: t-api,RFC

OpenCV 3.x and 4.x invalidates memory addresses of `USAGE_ALLOCATE_SHARED_MEMORY` UMat data (i.e. OpenCL SVM data) when it copies/moves it during (re)allocation because a copy/move changes the memory address of that data. The raison d'être for SVM is to have a single unchanging address space. Copy/move invalidates memory addresses. This may not be a problem for dumb data (e.g. RGB picture) but it is a problem for data with pointers (e.g. linked lists).

#### System information (version)
- OpenCV => all
- Operating System / Platform => all
- Compiler => all

#### Detailed description

In 2013, OpenCL 2.x introduced SVM (shared virtual memory) as a feature. SVM allows the cpu and OpenCL compute device to have the same address space. All major gpu manufacturers support it (various feature levels) and SVM is an optional compile feature of OpenCV 3.x and 4.x. https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#shared-virtual-memory

SVM is needed when code+data needs a single address space, e.g. a linked-list. Most linked-lists have nodes and each node has a pointer to the next node. Those pointers are absolute memory address pointers within the same address space. A cpu could initially create the linked list and then give that linked list to the OpenCL compute device for use. Since they share a single address space, both cpu and OpenCL device can operate on the linked-list. The pointers are valid for both. Please note, a single address space *does not* imply simultaneous access by cpu and device.

In both OpenCV 3.x and 4.x, this will fail. Pseudocode...

```c++
cv::Mat host_linked_list(1, 10000000, CV_8U);
initialize_linked_list(host_linked_list); // uses `Mat::data` and `size` to initialize a linked-list within the memory block
cv::UMat svm_linked_list = host_linked_list.getUMat(ACCESS_RW, USAGE_ALLOCATE_SHARED_MEMORY);
ocl::Kernel my_list_operation = get_my_kernel();
my_list_operation.args(KernelArg::ReadWrite(svm_linked_list)).run();
// the kernel will crash and likely the program
```

In contrast, this code will succeed...

```c++
cv::UMat svm_linked_list(1, 10000000, CV_8U, USAGE_ALLOCATE_SHARED_MEMORY);
initialize_linked_list(svm_linked_list.getMat(ACCESS_RW)); // uses `Mat::data` and `size` to initialize a linked-list within the memory block
ocl::Kernel my_list_operation = get_my_kernel();
my_list_operation.args(KernelArg::ReadWrite(svm_linked_list)).run();
// works correctly
```

Below is the problem area in 3.x. There is existing data (e.g. linked list) at the address pointed to by `u->origdata`. The errant code then copies that data to a new memory address pointed to by `handle`. This will invalidate the linked list. The new copy of the linked list at `handle` will have pointers that point to the block of memory at `u->origdata`. The linked list copy is unuseable and will crash the kernel and likely crash the program.

https://github.com/opencv/opencv/blob/4d587c341b7029005e0599be94bdc5f124290a1f/modules/core/src/ocl.cpp#L4805-L4815

How can a caller get to this section of code? I think `Mat::getUMat()`, `UMat::clone()`, and `UMat::copyTo()` are all candidates. It is some scenario where...

1. device and driver are SVM capable
2. OpenCV is compiled and configure to enable SVM
3. `UMatUsageFlags = USAGE_ALLOCATE_SHARED_MEMORY`

This is not a problem with dumb data, e.g. RGB values. It is questionable if dumb data needs the SVM feature. The rare and exotic (SVM fine-grain system) can be of use, but no mainstream desktop computer or laptop supports this today. https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#shared-virtual-memory

*It is a problem* for data that contains memory addresses/pointers (e.g. linked lists).

#### Recommendation

1. Document this as a strong warning. More analysis is needed on how best to document this.
2. Perhaps a code change to prevent it. It is possible to add error/throw code which would prevent these copies/moves. The issue to consider is that: dumb data is safe, other data might crash. So does OpenCV block it all to be safe?

##### Issue submission checklist

 - [X] I report the issue, it's not a question
 - [X] I checked the problem with documentation, FAQ, open issues,
       forum.opencv.org, Stack Overflow, etc and have not found solution
 - [X] I updated to latest OpenCV version and the issue is still there
 - [X] There is reproducer code and related data files: videos, images, onnx, etc