Pointer Types

Making it easier to work with shaders


Pointer Types

A pointer to type T represents an address of an object of type T.

⚠️ Warning: Pointers are not yet fully implemented in slangc.

Current limitations include:

  • Pointers to local memory are supported only on CUDA and CPU targets.
  • Slang does not support pointers to opaque handle types such as Texture2D. For handle pointers, use DescriptorHandle<T> instead.
  • Slang does not currently support const pointers.
  • Slang does not support custom alignment specification. Functions loadAligned() and storeAligned() may be used for loads and stores using pointers with known alignment.
  • Pointers are not supported on all targets.
  • Slang does not currently support inheritance with pointers. In particular, a pointer to a structure conforming to interface I cannot be cast to a pointer to I.

See also GitHub issue #9061.

Declaration Syntax

simple-type-id-spec =
    [modifier-list]
    type-identifier
    [generic-params-decl]
    ('[' [constant-index-expr] ']' | '*' )*

See type specifier syntax for full type specifier syntax.

📝 Remark 1: A pointer type specified with the declaration syntax is equivalent to generic pointer type Ptr<T, Access.ReadWrite, AddressSpace.Device>.

📝 Remark 2: Pointers can also be declared using variable declarations. In this case, a variable is declared as a pointer to a type, rather than the type itself being a pointer type.

Parameters

Generic Pointer Types

Type aliases provided by the Slang standard library:

Parameters

  • T is the element type.
  • AccessMode is the storage access mode.
  • AddressSpace is the storage address space.

See pointer traits.

Description

The pointer declaration * applied to a base type creates a pointer type. The base type may be any addressable type including pointer and array types.

To obtain the address of an object, the address-of operator & is used. The address may be assigned to a pointer variable with a matching type. Alternatively, __getAddress(obj) may be used.

To access the pointed-to object, the pointer dereference operator * is used. If the pointed-to type is a structure or a class type, the member access operators . or -> may be used to dereference the pointer and access a member.

When a pointer points to an array element, an integer value may be added to or subtracted from it. The resulting pointer points to an element offset by that value.

A pointer value belongs to one of the following classes:

  • a pointer to an object with matching traits, including a pointer to an array element
  • a pointer past the end of an object
  • a null pointer, which is a special pointer value that points to nothing
  • an invalid pointer, otherwise.

It is undefined behavior to dereference a pointer that does not point to an object with matching traits.

For a comprehensive description, see pointer expressions (TODO).

⚠️ Warning: When a pointer is to an element in a multi-dimensional array, pointer arithmetic must always result in a pointer that is in the same innermost array or a pointer past the last object in the array (which may not be dereferenced). Any other result is undefined behavior.

📝 Remark 1: Currently, there are no const pointers in Slang. Pointers to read-only data and immutable data may be declared with generic pointer types.

📝 Remark 2: Consider the following pointer arithmetic:

var arr : uint[10] = { };
var ptr : uint *;

ptr = &arr[9]; // OK: ptr points to the last element
               // of the array

ptr++;         // Still OK: ptr points to one past the
               // last element

ptr++;         // Pointer is now invalid

ptr--;         // No validity guarantees with invalid
               // pointers in pointer expressions;
               // dereferencing would be undefined behavior

Pointer Traits

A pointer type has the following traits:

  • type of the pointed-to object
  • access mode
  • address space

A valid pointer may only point to objects with matching traits.

The default pointer address space is AddressSpace.Device, and the default access mode is Access.ReadWrite. It is not possible to use different address spaces or access modes using the declaration syntax.

Pointers for other address spaces and access modes may be declared by using type alias Ptr<T, AccessMode, AddressSpace> provided by the standard library. There is no implicit conversion from read-write to read-only pointers.

Examples

Pointers Denoting a Range

RWStructuredBuffer<uint> outputBuffer;

cbuffer Globals
{
    Ptr<uint> g_inputData;
    uint g_inputDataLen;
}

// Calculate sum of half-open range [start, end)
uint sumOfValues(uint *start, uint *end)
{
    uint sum = 0;

    for (uint *i = start; i != end; ++i)
    {
        sum = sum + *i;
    }

    return sum;
}

[numthreads(1, 1, 1)]
void main(uint3 id : SV_DispatchThreadID)
{
    // Calculate sum of elements 0, 1, ..., 9 provided
    // the input data buffer is big enough.
    outputBuffer[id.x] +=
        sumOfValues(
            g_inputData, &g_inputData[min(g_inputDataLen, 10)]);
}