Edit

Memory2D class

The Memory2D is a type that mirrors the functionality of the Memory type, with the difference being that it can be used to represent 2D memory locations. It is extremely flexible and is capable of wrapping a number of different types, including ND arrays (with explicit support for 1D, 2D, and 3D arrays) or Memory instances. This type is meant to be used together with the Span2D type, in the same way that Memory is used along with Span. For more info on the key differences and use case scenarios of these two types, see Memory usage guidelines.

Platform APIs: Memory2D, Span2D, ReadOnlyMemory2D

How it works

The Memory2D type internally tracks the mapped 2D memory area through a reference to the wrapped object, the height and width parameters, and a special pitch parameter. The height and width indicate the length of the rows and columns in the 2D memory area, while the pitch indicates the offset between the end of each row and the start of the following one.

Here's a simple diagram that illustrates this configuration (the "XX" cells in the grid represent items belonging to the target 2D memory area):

//                _____________________stride_____...
//  reference__  /________width_________  ________...
//             \/                       \/
// | -- | -- | |- | -- | -- | -- | -- | -- | -- | -- |_
// | -- | -- | XX | XX | XX | XX | XX | XX | -- | -- | |
// | -- | -- | XX | XX | XX | XX | XX | XX | -- | -- | |
// | -- | -- | XX | XX | XX | XX | XX | XX | -- | -- | |_height
// | -- | -- | XX | XX | XX | XX | XX | XX | -- | -- |_|
// | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
// | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
// ...__pitch__/
// ...________/

This configuration allows Memory2D to be extremely flexible in the way it maps existing buffers to 2D memory areas, as it makes it possible to also represent discontiguous buffers as a "virtual" 2D memory location. Following are a few examples of buffer types that a Memory2D instance can map to:

  • A 1D T[] array that's mapped as a 2D memory area in row-major order.
  • A 2D T[,] array, mapped directly to a Memory2D instance.
  • A 3D T[,,] array, with a Memory2D instance representing a given depth slice (a layer).

The Memory2D type also exposes a number of utility methods, including most of the same API surface that the standard Memory implements. For instance, it includes a Slice(int, int) method that makes it easy to do 2D slicing operations directly on the virtual 2D memory location, with the Memory2D instance automatically adjusting the necessary parameters internally to shift its mapping on the right memory areas corresponding to the requested result.

Syntax

Here's how you can create a Memory2D instance from a 2D array:

int[,] array =
{
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};

Memory2D memory = array;

// The memory directly maps the 2*3 array here.
Memory2D slice = memory.Slice(0, 1, 2, 2);

// Create a slice from row 0 and column 1, of size 2*2.
int[,] copy = slice.ToArray();

// { 2, 3 }
// { 5, 6 }

// If on a supported runtime, you can also slice using a range:
Memory2D test = memory[.., ..2];

// { 1, 2 }
// { 4, 5 }
// { 7, 8 }

Span2D span = memory.Span;

// You can use the span to perform operations on the underlying
// data for the memory instance. All the available APIs are
// documented in the docs about the Span2D type.

ReadOnlyMemory2D

The ReadOnlyMemory2D type is to the Memory2D type what ReadOnlyMemory is to Memory. It exposes the same exact functionalities (minus the APIs that involve modifying the contents of the wrapped memory area) and provides a read-only view to arbitrary 2D memory locations. For more info on how this type works, see the previous paragraph on the Memory2D type.

Examples

You can find more examples in the unit tests.