DeviceArray Reference

Introduction

DeviceArray is a handle to a block of data that lives in GPU memory instead of CPU memory. It is reference-counted, so the data stays alive as long as at least one handle to it exists.

This page describes the data layout: how each pixel or point of a DeviceArray is stored in memory, for every supported format.

If you run your own GPU code (a CUDA or OpenCL kernel, or a framework such as PyTorch, CuPy, or OpenCV) against the buffer, see DeviceArray — Stream, Queue and Context for how the SDK orders its work against yours and when a shared GPU context is required. For a task-oriented walkthrough with code samples, see GPU Access Tutorial.

Data Layout

Every DeviceArray<Format> stores its elements in row-major order with channels interleaved. The channel count is determined by Format and never varies at runtime. Whether the buffer is 1D, 2D, or 3D depends on the channel count of the format and whether the source is organized or unorganized.

Format catalog

Format

Element type

Channels

Bytes / element

Typical source

PointXYZ

float

3

12

PointCloud.

PointXYZW

float

4

16

PointCloud (GPU-aligned).

PointZ

float

1

4

PointCloud (depth map).

SNR

float

1

4

PointCloud.

NormalXYZ

float

3

12

PointCloud.

ColorRGBA / BGRA (+ SRGB)

uint8_t

4

4

Frame2D / PointCloud.

ColorRGBAf

float

4

16

Frame2D (linear float).

ColorRGB / BGR (+ SRGB)

uint8_t

3

3

Frame2D.

Shape and stride rules

The shape depends on channel count and organization. Strides are in element counts (not bytes) and follow row-major C order.

Case

Dimensions

Shape

Strides (elements)

Organized, multi-channel

3

[H, W, C]

[W*C, C, 1].

Organized, single-channel

2

[H, W]

[W, 1].

Unorganized, multi-channel

2

[N, C]

[C, 1].

Unorganized, single-channel

1

[N]

[1].

Use stridesInBytes() when the consumer framework wants byte strides.

Interleaved multi-channel formats

An organized multi-channel buffer such as DeviceArray<PointXYZ> from an image of height H and width W is one tightly packed block. Each pixel contributes C consecutive elements before the next pixel begins. There are no per-plane offsets and no padding between rows.

The following diagram illustrates a 2x3 PointXYZ buffer. Each pixel (r, c) holds three floats X, Y, Z, laid out consecutively in memory.

Pixel grid (shape = [2, 3, 3]):

  col 0            col 1            col 2
+----------------+----------------+----------------+
| X00 Y00 Z00    | X01 Y01 Z01    | X02 Y02 Z02    |  row 0
+----------------+----------------+----------------+
| X10 Y10 Z10    | X11 Y11 Z11    | X12 Y12 Z12    |  row 1
+----------------+----------------+----------------+

Flat memory (row-major, channel-interleaved):

offset (floats):  0   1   2   3   4   5   6   7   8   9  10  11 ...
                +---+---+---+---+---+---+---+---+---+---+---+---+
                |X00|Y00|Z00|X01|Y01|Z01|X02|Y02|Z02|X10|Y10|Z10|...
                +---+---+---+---+---+---+---+---+---+---+---+---+
                 \_________/ \_________/ \_________/
                 pixel (0,0) pixel (0,1) pixel (0,2)

strides (elements): [W*C=9, C=3, 1]
strides (bytes)  : [36,     12,   4]

The same layout applies to PointXYZW (4 channels), NormalXYZ (3), ColorRGBA / BGRA and their SRGB variants (4x uint8), ColorRGBAf (4x float), and ColorRGB / BGR (3x uint8). Only the channel count and element type change.

Tip

PointXYZW exists so that each point is 16-byte aligned, which most GPU APIs and vector loads prefer. ColorRGB / BGR at 3 bytes per pixel is not naturally aligned; prefer the 4-channel variants when the consumer benefits from alignment.

Planar single-channel formats

Formats with one channel (PointZ, SNR) have no channel axis. An organized buffer is a plain 2D matrix.

Pixel grid (shape = [2, 3]):

  col 0     col 1     col 2
+---------+---------+---------+
| Z00     | Z01     | Z02     |  row 0
+---------+---------+---------+
| Z10     | Z11     | Z12     |  row 1
+---------+---------+---------+

Flat memory (row-major):

offset:  0    1    2    3    4    5
       +----+----+----+----+----+----+
       |Z00 |Z01 |Z02 |Z10 |Z11 |Z12 |
       +----+----+----+----+----+----+

strides (elements): [W=3, 1]
strides (bytes)  : [12,   4]     (float)

Unorganized point clouds

An unorganized PointCloud produces a flat list of N elements with no height. Multi-channel formats collapse the row dimension and keep interleaved channels. Single-channel formats collapse to plain 1D.

Unorganized PointXYZ (shape = [N, 3]):

offset (floats): 0   1   2   3   4   5   6   7   8   ...
               +---+---+---+---+---+---+---+---+---+
               |X0 |Y0 |Z0 |X1 |Y1 |Z1 |X2 |Y2 |Z2 |...
               +---+---+---+---+---+---+---+---+---+
                \_________/ \_________/ \_________/
                point 0     point 1     point 2

strides (elements): [3, 1]

Unorganized SNR (shape = [N]):

offset (floats): 0    1    2    3    ...
               +----+----+----+----+
               |s0  |s1  |s2  |s3  |...
               +----+----+----+----+
strides (elements): [1]

Reading the layout at runtime

The metadata accessors mirror the model above.

  • shape() returns a std::vector<int> of length 1, 2, or 3.

  • strides() returns strides in element counts.

  • stridesInBytes() returns strides in bytes.

  • size() returns the number of logical elements (points or pixels, not channels).

  • sizeInBytes() returns the total byte size of the buffer.

  • backend() returns ComputeBackend::cuda or ComputeBackend::opencl.

See Also