Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This post assumes and requires that you have read the introductory post to this series which also includes a table of content. With that out of the way let’s look at restrictions with pointer operations and casting.
Since pointers in C++ AMP are actually emulated on top of the DirectX 11 platform which does not support pointers, to prevent patterns that may result in extremely inefficient emulated code, we disallow casting a pointer to an integral type, nor an integral type to a pointer. This restriction applies to reinterpret_cast as well as to C-style casts. Note that the implicit casting from constant 0 to any pointer type and from any pointer type to bool is still allowed, and is treated as the null pointer just like regular C++. For example,
int n1 = 4;
int *p1 = 0; // legal: 0 -> int*
int *p2 = reinterpret_cast<int*>(n1); // illegal: int -> int *
int n2 = (int)p2; // illegal: int* –> int
void *p3 = p1; // legal: int* -> void*
if (p2) n1 = 5; // legal: int* -> bool
In addition, casting away constness from a pointer or reference will result in a compiler warning and/or undefined behavior. This is because we rely on constness to decide what kind of underlying GPU memory access mode (read-only or writable) to use and try to exploit readonliness as much as possible to achieve better performance. Casting away constness may result in writing into a read-only GPU buffer, which is not allowed. For example,
extent<1> e(10);
array<int, 1> a(e);
array<int, 1> b(e);
const array<int, 1> &ra = a;
parallel_for_each(a.extent, [&] (index<1> idx) restrict(amp){
b[idx] = idx[0];
int *p = (int *)(&ra[idx]); // ra[idx] returns a “const int&”, cast &ra[idx]
// to “int*” triggers a warning
*p = idx[0]; // it's undefined whether the value of idx[0] is written into ra[idx]
});
Finally, pointer arithmetic is not allowed to be performed on pointers to bool values since that will result in invalid pointers pointing to an unaligned data region.
struct A
{
bool flag;
int data;
};
A a;
bool *p1 = &(a.flag);
bool *p2 = p1++; // illegal, p2 now points to unaligned data region
bool b = *(p2); // undefined!