Resource Types[Resources]

9 Resource Types[Resources]

Resources are built-in intangible types representing memory with an external interface.

These take the form of Typed Buffers, Raw Buffers, Textures, Constant Buffers and Samplers.

Buffer and Texture types can be read-only or writable.

9.1 Typed Buffers[Resources.tybufs]

The typed buffer class template represents a one-dimensional resource containing an array of a single given type. Its contents are indexed by typed access to each element Types may have their formats converted upon load.

The element type may be any type up to 16 bytes in size. Elements may be padded to 16 bytes if the element type is smaller than 16 bytes.

All typed buffers can be read through subscript operators or Load methods. Writable typed buffers can be written through subscript operators.

Where T can be any arithmetic type 3.9.1 or a vector with a maximum of four elements containing such an arithmetic type. The total size of a single contained element must be less than 16 bytes.

Typed buffers perform format conversions on load such that the underlying data gets converted to the destination type.

9.1.1 Constructors[Resources.tybufs.ctrs]

Read-only Buffers can be defined with explicit or implicit template parameter types.

Buffer buf1; Buffer<> buf2; Buffer<float4> buf3;

Since float4 is the default type, all of these definitions are equivalent.

RWBuffers must be defined with explicit template parameter types.

RWBuffer<float4> buf;

When defined at global scope, typed buffers are bound to externally-defined backing stores using the explicit binding location if provided or the implicit binding if not (9.8).

When defined at local scope, typed buffers represent local references that can be associated with global buffers when assigned, but must be resolvable to a unique global buffer declaration.

In the case of a buffer array declaration, a unique global declaration references all the buffers in the array. Local buffer assignments can map to different resource array elements depending on runtime values.

Buffer<int> grobuf; RWBuffer<int> grwbuf; void main() Buffer<int> lrobuf = grobuf; RWBuffer<int> lrwbuf = grwbuf;

Buffers cannot be implicitly nor explicitly cast from one type to another. This means that local buffers can only be assigned from buffers with the same element type.

9.1.2 Dimensions[Resources.tybufs.dims]

The size of a typed buffer can be retrieved using the GetDimensions method.

void GetDimensions(out uint width) const;

This returns the full length, in elements of the buffer through the width out parameter.

9.1.3 Element Access[Resources.tybufs.access]

The contents of typed buffers can be retrieved using the Load methods or the subscript operator.

T Load(in int index) const; T operator[](int index) const;

These each return the element of the buffer’s type at the given index index.

An additional Load method returns the indicated element just as the other, but also takes a second status parameter that returns information about the accessed resource.

T Load(in int index, out uint status) const;

The status parameter returns an indication of whether all of the retrieved value came from fully mapped parts of the resource. This parameter must be passed to the built-in function CheckAccessFullyMapped (9.7) in order to interpret it.

Writable buffers have an additional subscript operator that allows assignment to an element of the buffer. It behaves as if it returns a reference to that element.

T &operator[](int index);

Partial writes aren’t allowed. Assignment to individual vector elements will result in an error.

9.2 Raw Buffers[Resources.rawbufs]

Raw buffers are one-dimensional resources of arbitrary memory layout. They are either ByteAddressBuffers or StructuredBuffers. ByteAddressBuffers enable per-byte access to the raw data while StructuredBuffers have an associated structure type that determines how they are indexed. This type can be a scalar, vector, matrix, or user-defined struct.

9.3 Byte Access Buffers[Resources.babufs]

class ByteAddressBuffer

public: ByteAddressBuffer(); ByteAddressBuffer(const ByteAddressBuffer &buf); ByteAddressBuffer &operator=(ByteAddressBuffer &buf);

void GetDimensions(out uint size) const;

// Element access. uint Load(in uint offset) const; uint2 Load2(in uint offset) const; uint3 Load3(in uint offset) const; uint4 Load4(in uint offset) const; template<typename T> T Load(in uint offset) const;

uint Load(in uint offset, out uint status) const; uint2 Load2(in uint offset, out uint status) const; uint3 Load3(in uint offset, out uint status) const; uint4 Load4(in uint offset, out uint status) const; template<typename T> T Load(in uint offset, out uint status) const;

;

class RWByteAddressBuffer : public ByteAddressBuffer

public: RWByteAddressBuffer(); RWByteAddressBuffer(const RWByteAddressBuffer &buf); RWByteAddressBuffer &operator=(RWByteAddressBuffer &buf);

// Element assignment. void Store(in uint offset, in uint value); void Store2(in uint offset, in uint2 value); void Store3(in uint offset, in uint3 value); void Store4(in uint offset, in uint4 value); template<typename T> void Store(in uint offset, in T value);

// 32-bit integer atomic arithmetic/bitwise operations. void InterlockedAdd(in uint offset, in uint value); void InterlockedAdd(in uint offset, in uint value, out uint original); void InterlockedAnd(in uint offset, in uint value); void InterlockedAnd(in uint offset, in uint value, out uint original); void InterlockedOr(in uint offset, in uint value); void InterlockedOr(in uint offset, in uint value, out uint original); void InterlockedXor(in uint offset, in uint value); void InterlockedXor(in uint offset, in uint value, out uint original);

// 32-bit integer atomic comparison operations void InterlockedMin(in uint offset, in int value); void InterlockedMin(in uint offset, in uint value); void InterlockedMin(in uint offset, in int value, out int original); void InterlockedMin(in uint offset, in uint value, out uint original); void InterlockedMax(in uint offset, in int value); void InterlockedMax(in uint offset, in uint value); void InterlockedMax(in uint offset, in int value, out int original); void InterlockedMax(in uint offset, in uint value, out uint original);

// 32-bit integer atomic compare/exchange operations void InterlockedCompareStore(in uint offset, in uint compare, in uint value); void InterlockedExchange(in uint offset, in uint value, out uint original); void InterlockedCompareExchange(in uint offset, in uint compare, in uint value, out uint original);

// 64-bit integer atomic arithmatic/bitwise operations void InterlockedAdd64(in uint offset, in uint64_t value); void InterlockedAdd64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedAnd64(in uint offset, in uint64_t value); void InterlockedAnd64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedOr64(in uint offset, in uint64_t value); void InterlockedOr64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedXor64(in uint offset, in uint64_t value); void InterlockedXor64(in uint offset, in uint64_t value, out uint64_t original);

// 64-bit integer atomic comparison operations void InterlockedMin64(in uint offset, in int64_t value); void InterlockedMin64(in uint offset, in int64_t value, out int64_t original); void InterlockedMin64(in uint offset, in uint64_t value); void InterlockedMin64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedMax64(in uint offset, in int64_t value); void InterlockedMax64(in uint offset, in int64_t value, out int64_t original); void InterlockedMax64(in uint offset, in uint64_t value); void InterlockedMax64(in uint offset, in uint64_t value, out uint64_t original);

// 64-bit integer atomic compare/exchange operations void InterlockedCompareStore64(in uint offset, in uint64_t compare, in uint64_t value); void InterlockedExchange64(in uint offset, in int64_t value, out int64_t original); void InterlockedCompareExchange64(in uint offset, in uint64_t compare, in uint64_t value, out int64_t original);

// 32-bit float atomic compare/exchange operations void InterlockedCompareStoreFloatBitwise(in uint byteOffest, in float compare, in float value); void InterlockedExchangeFloat(in uint byteOffest, in float value, out float original); void InterlockedCompareExchangeFloatBitwise(in uint byteOffest, in float compare, in float value, out float original);

;

9.3.1 Constructors[Resources.babufs.ctrs]

Since their contents are viewed as raw bytes, ByteAddressBuffers are defined without any type parameters.

ByteAddressBuffer robuf; RWByteAddressBuffer rwbuf;

When defined at global scope, ByteAccessBuffers are bound to externally-defined backing stores using the explicit binding location if provided or the implicit binding if not (9.8).

When defined at local scope, ByteAccessBuffers represent local references that can be associated with global ByteAccessBuffers when assigned, but must be resolvable to a unique global buffer declaration.

ByteAddressBuffer grobuf; RWByteAddressBuffer grwbuf; void main() ByteAddressBuffer lrobuf = grobuf; RWByteAddressBuffer lrwbuf = grwbuf;

9.3.2 Dimensions[Resources.babufs.dims]

The size of a ByteAddressBuffer can be retrieved using the GetDimensions method.

void GetDimensions(out uint size) const;

This returns the full size of the buffer in bytes through the size out parameter.

9.3.3 Element Access[Resources.babufs.access]

The contents of ByteAddressBuffers can be retrieved using the Load methods.

uint Load(in uint offset) const; uint2 Load2(in uint offset) const; uint3 Load3(in uint offset) const; uint4 Load4(in uint offset) const;

These each return the bytes at the given byte offset into the buffer offset in the form of one or more unsigned integers. The offset address must be a multiple of 4. Each of the variants returns a number of bytes corresponding to the size of the uint vector returned.

An additional templated load method allows returning the bytes at the given byte offset in the form of the type given in the template parameter. This can be a scalar, vector, matrix, or user-defined struct.

template<typename T> T Load(in uint offset) const;

The alignment requirements of offset for this operation is the alignment requirement of an object of type T in the device memory space (1.7.2).

Additional Load methods return the same values as the others, but also take a second status parameter that returns information about the accessed resource.

uint Load(in uint offset, out uint status) const; uint2 Load2(in uint offset, out uint status) const; uint3 Load3(in uint offset, out uint status) const; uint4 Load4(in uint offset, out uint status) const; template<typename T> T Load(in uint offset, out uint status) const;

The status parameter returns an indication of whether all of the retrieved value came from fully mapped parts of the resource. This parameter must be passed to the built-in function CheckAccessFullyMapped (9.7) in order to interpret it.

9.3.4 Atomic Operations[Resources.babufs.atomics]

RWByteAddressBuffers have a suite of atomic methods that perform the given operation on type-appropriate-sized element data at the given buffer offset in a way that ensures no contention from other threads performing other operations. Each of these operates on two 32 or 64 bit values: the given parameter value and the buffer value. The buffer value is a 32 or 64 bit value at a given offset into the buffer. Each method has an overload that returns the original buffer value before the atomic operation was performed.

void InterlockedAdd(in uint offset, in uint value); void InterlockedAdd(in uint offset, in uint value, out uint original); void InterlockedAnd(in uint offset, in uint value); void InterlockedAnd(in uint offset, in uint value, out uint original); void InterlockedOr(in uint offset, in uint value); void InterlockedOr(in uint offset, in uint value, out uint original); void InterlockedXor(in uint offset, in uint value); void InterlockedXor(in uint offset, in uint value, out uint original);

Perform atomic addition, bitwise and, bitwise or, or bitwise exclusive or on the 32-bit integer buffer value at the byte offset offset and the provided value. Store the result to that offset buffer location, optionally returning the original buffer value through original.

void InterlockedMin(in uint offset, in int value); void InterlockedMin(in uint offset, in uint value); void InterlockedMin(in uint offset, in int value, out int original); void InterlockedMin(in uint offset, in uint value, out uint original); void InterlockedMax(in uint offset, in int value); void InterlockedMax(in uint offset, in uint value); void InterlockedMax(in uint offset, in int value, out int original); void InterlockedMax(in uint offset, in uint value, out uint original);

Perform the sign-approrpriate minimum or maximum comparison on the 32-bit integer buffer value at the byte offset offset and the provided value. Store the lesser or greater value, as appropriate, to that offset buffer location, optionally returning the original buffer value through original.

void InterlockedExchange(in uint offset, in uint value, out uint original);

Performs an atomic exchange of the 32-bit integer buffer value at the byte offset offset with the provided value. Stores value at the offset buffer location and returns the original buffer value through original.

void InterlockedCompareStore(in uint offset, in uint compare, in uint value); void InterlockedCompareExchange(in uint offset, in uint compare, in uint value, out uint original);

Perform an atomic exchange of or store to the 32-bit integer buffer value at the byte offset offset with the provided value if the value at that location matches the value of compare. InterlockedCompareExchange returns the original buffer value through original.

void InterlockedAdd64(in uint offset, in uint64_t value); void InterlockedAdd64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedAnd64(in uint offset, in uint64_t value); void InterlockedAnd64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedOr64(in uint offset, in uint64_t value); void InterlockedOr64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedXor64(in uint offset, in uint64_t value); void InterlockedXor64(in uint offset, in uint64_t value, out uint64_t original);

Perform atomic addition, bitwise and, bitwise or, or bitwise exclusive or on the 64-bit integer buffer value at the byte offset offset and the provided value. Store the result to that offset buffer location, optionally returning the original buffer value through original.

void InterlockedMin64(in uint offset, in int64_t value); void InterlockedMin64(in uint offset, in uint64_t value); void InterlockedMin64(in uint offset, in int64_t value, out int64_t original); void InterlockedMin64(in uint offset, in uint64_t value, out uint64_t original); void InterlockedMax64(in uint offset, in int64_t value); void InterlockedMax64(in uint offset, in uint64_t value); void InterlockedMax64(in uint offset, in int64_t value, out int64_t original); void InterlockedMax64(in uint offset, in uint64_t value, out uint64_t original);

Perform the sign-approrpriate minimum or maximum comparison on the 64-bit integer buffer value at the byte offset offset and the provided value. Store the lesser or greater value, as appropriate, to that offset buffer location, optionally returning the original buffer value through original.

void InterlockedExchange64(in uint offset, in uint64_t value, out uint64_t original);

Performs an atomic exchange of the 64-bit integer buffer value at the byte offset offset with the provided value. Stores value at the offset buffer location and returns the original buffer value through original.

void InterlockedCompareStore64(in uint offset, in uint64_t compare, in uint64_t value); void InterlockedCompareExchange64(in uint offset, in uint64_t compare, in uint64_t value, out uint64_t original);

Perform an atomic exchange of or store to the 64-bit integer buffer value at the byte offset offset with the provided value if the value at that location matches the value of compare. InterlockedCompareExchange returns the original buffer value through original.

void InterlockedExchangeFloat(in uint byteOffest, in float value, out float original);

Performs an atomic exchange of the 32-bit float buffer value at the byte offset offset with the provided value. Stores value at the offset buffer location and returns the original buffer value through original.

void InterlockedCompareStoreFloatBitwise(in uint byteOffest, in float compare, in float value); void InterlockedCompareExchangeFloatBitwise(in uint byteOffest, in float compare, in float value, out float original);

Perform an atomic exchange of or store to the 32-bit float buffer value at the byte offset offset with the provided value if the value at that location matches the value of compare in a bitwise comparison. InterlockedCompareExchangeFloatBitwise returns the original buffer value through original.

Unlike standard floating point comparisons, values will only match if the bit representation matches which can miss some matching values that have different bit repesantations in addition to ignoring floating point rules surrounding NaN and infinite values.

9.4 Structured Buffers[Resources.stbufs]

Structured buffers are raw buffers with associated types that facilitate indexing. Unlike typed buffers, they perform no format conversions. The buffer contents is treated as raw data. Accessors return the contained bytes as the target type with no conversions or interpolations applied. Structured buffers can be defined with scalar, vector, matrix, or user-defined struct elements.

Structured buffers can be read-only, writable, appendable, or consumable. Writable buffers can have their elements assigned in arbitrary locations. Append structured buffers can only have elements added to the end. Consume structured buffers can only have elements removed from the end.

template <typename T> class StructuredBuffer

public: StructuredBuffer(); StructuredBuffer(const StructuredBuffer &buf); StructuredBuffer &operator=(StructuredBuffer &buf);

void GetDimensions(out uint count, out uint stride) const;

// Element access. T operator[](int index) const; T Load(in int index) const; T Load(in int index, out uint status) const;

;

template <typename T> class RWStructuredBuffer : public StructuredBuffer

public: RWStructuredBuffer(); RWStructuredBuffer(const RWStructuredBuffer &buf); RWStructuredBuffer &operator=(RWStructuredBuffer &buf);

// Element assignment. T &operator[](int index);

// Hidden counter increment/decrement. uint IncrementCounter(); uint DecrementCounter();

;

template <typename T> class AppendStructuredBuffer

public: AppendStructuredBuffer(); AppendStructuredBuffer(const AppendStructuredBuffer &buf); AppendStructuredBuffer &operator=(AppendStructuredBuffer &buf);

void GetDimensions(out uint count, out uint stride) const;

void Append(in T value);

;

template <typename T> class ConsumeStructuredBuffer

public: ConsumeStructuredBuffer(); ConsumeStructuredBuffer(const ConsumeStructuredBuffer &buf); ConsumeStructuredBuffer &operator=(ConsumeStructuredBuffer &buf);

void GetDimensions(out uint count, out uint stride) const;

T Consume();

;

9.4.1 Constructors[Resources.stbufs.ctrs]

Structured buffers must be defined with explicit template parameter types.

struct S int i; float f;; StructuredBuffer<S> robuf1; StructuredBuffer<float4> robuf2; StructuredBuffer<float2x3> robuf3;

RWStructuredBuffer<S> rwbuf1; RWStructuredBuffer<float4> rwbuf2; RWStructuredBuffer<float2x3> rwbuf3;

AppendStructuredBuffer<S> apbuf1; AppendStructuredBuffer<float4> apbuf2; AppendStructuredBuffer<float2x3> apbuf3;

ConsumeStructuredBuffer<S> cobuf1; ConsumeStructuredBuffer<float4> cobuf2; ConsumeStructuredBuffer<float2x3> cobuf3;

When defined at global scope, structured buffers are bound to externally-defined backing stores using the explicit binding location if provided or the implicit binding if not (9.8).

When defined at local scope, structured buffers represent local references that can be associated with global buffers when assigned, but must be resolvable to a unique global buffer declaration.

Resource types contained in structs are only allocated registers when they are explicitly used. This includes elements of arrays of resources as such array elements must be indexed with literals.

StructuredBuffer<int3x3> grobuf; RWStructuredBuffer<int3x3> grwbuf; AppendStructuredBuffer<int3x3> gapbuf; ConsumeStructuredBuffer<int3x3> gcobuf; void main() StructuredBuffer<int3x3> lrobuf = grobuf; RWStructuredBuffer<int3x3> lrwbuf = grwbuf; AppendStructuredBuffer<int3x3> lbuf = gapbuf; ConsumeStructuredBuffer<int3x3> lcobuf = gcobuf;

Structured buffer operands to the assignment operator must have the same element type.

9.4.2 Dimensions[Resources.stbufs.dims]

The structure count and stride of a structured buffer can be retrieved using the GetDimensions method.

void GetDimensions(out uint count, out uint stride);

This returns number of structured elements of the buffer through the count out parameter and the size of each element in bytes through the stride out parameter.

9.4.3 Element Access[Resources.stbufs.access]

The contents of read-only StructuredBuffers and writable RWStructuredBuffers can be retrieved using the Load methods or the subscript operator.

T Load(in int index) const; T operator[](int index) const;

These each return the element of the buffer’s type at the given index index.

An additional Load method returns the indicated element just as the other, but also takes a second status parameter that returns information about the accessed resource.

T Load(in int index, out uint status) const;

The status parameter returns an indication of whether all of the retrieved value came from fully mapped parts of the resource. This parameter must be passed to the built-in function CheckAccessFullyMapped (9.7) in order to interpret it.

Writable RWStructuredBuffers have an additional subscript operator that allows assignment to a structure element of the buffer. It behaves as if it returns a reference to that element.

T &operator[](int index);

9.4.4 Counter Manipulation[Resources.stbufs.counter]

RWStructuredBuffers may have a hidden counter that can be incremented and decremented using methods.

uint IncrementCounter(); uint DecrementCounter();

Increment or decrements the hidden counter associated with the RWStructuredBuffer. IncrementCounter returns the pre-increment value of the counter. DecrementCounter returns the post-decrement value of the counter.

9.4.5 Append[Resources.stbufs.append]

AppendStructuredBuffers can only be appended to as an output stream.

void Append(in T value);

Appends the value of the template parameter types to the end of the AppendStructuredBuffer. Subsequent appends will continue to add elements to the end of the buffer.

9.4.6 Consume[Resources.cnstbufs.consume]

ConsumeStructuredBuffers can only have values pulled from them as an input stream.

T Consume();

Removes and returns a value of the template parameter types from the end of the ConsumeStructuredBuffer.

9.5 Constant Buffers[Resources.cnbuf]

Constant buffers represent resources that contain read-only constant data in a well-defined memory layout. A constant buffer is declared either as a cbuffer-declaration (7.8) or as a declaration of Constant Buffer Class type (9.5.1).

9.5.1 Constant Buffer Class[Resources.cnbuf.cbclass]

Another way of declaring constant buffers is by using the ConstantBuffer<T> resource class.

The template parameter T must be a class type (10).

template <typename T> class ConstantBuffer public: ConstantBuffer(); ConstantBuffer(const ConstantBuffer &buf); ConstantBuffer &operator=(ConstantBuffer &buf); ;

The shader constants are the fields of the class type T. They can be referenced from anywhere within the translation unit after the ConstantBuffer<T> declaration as if they were fields of the ConstantBuffer<T> class.

For example:

struct MyConstants float4 CameraPos; ;

ConstantBuffer<MyConstants> CB;

float4 getCameraPosition() return CB.CameraPos;

The layout rules for constant buffer declared with the ConstantBuffer<T> syntax are the same as for named cbuffer declaration groups.

ConstantBuffer<T> can be defined at local scope to represent a local reference to a constant buffer that can be associated with a global buffer when assigned. The reference must be resolvable to a unique global buffer declaration before use.

Constant buffers cannot be implicitly nor explicitly cast from one type to another. This means that local ConstantBuffer can only be assigned from ConstantBuffer with the same template type T.

9.5.2 Constant Buffer Layout[Resources.cnbuf.lay]

Layout of the constant buffer is implementation dependent. This section describes the layout that is used by DirectX.

A constant buffer is arranged like an array of 16-byte rows, or 4-component vectors of 32-bit elements. Shader constants are arranged into the buffer in the order they were declared based on following rules.

Specific basic types are packed into the last used row of the buffer if they fit into the available space, starting at the next available aligned position. These types include:

  • scalar types

  • vector types

  • matrix types with only one row in column_major storage layout

If they do not fit the remaining space of the row, they will placed at the start a new 16-byte aligned row.

Vectors are aligned by the size of a single vector element type unless that alignment results in crossing the 16-byte row boundary, in which case it is aligned to the next row.

Aggregate types like arrays and structures are always 16-byte row-aligned. If the aggregate ends with an element that does not completely fill a row, the remaining space on the last row may be used by the next value.

Individual array elements are always 16-byte row aligned.

Matrix types with more than one row in column_major storage layout and matrix types in row_major storage layout in are aligned to the 16-byte row. Each row in storage layout (each column for column_major matrix) is aligned to a 16-byte row.

Members of structured types used in constant buffers follow these same rules. Because structures are always 16-byte row-aligned, the offset layout within the structure is independent of the particular structure instance location.

9.5.3 Packoffset annotations[Resources.cnbuf.po]

Shader constants declared in cbuffer declaration group can have an optional packoffset annotation added before their ; terminal. If this annotation is added to one shader constant in a declaration group then it must be added to all shader constants in that group.

packoffset-annotation:
: packoffset( packoffset-id packoffset-row packoffset-elementopt )

packoffset-id:one of
c C

packoffset-row:
digit
packoffset-row digit

packoffset-element:
. packoffset-element-id

packoffset-element-id:one of
x y z w r g b a

The packoffset annotation defines specific offset in the constant buffer where the shader constant is located.

The packoffset-row number is the index into the array of 16-byte rows of the constant buffer. Each row treated as a vector of four 32-bit elements.

The packoffset-element identifies specific location within the vector where x or r is the first element of the vector, y or g is the second one, z or b is the third one and w or a is the fourth, and last element of the vector.

Shader constant that has a structure, array or matrix type must always be 16-byte row-aligned. It means that if it specifies a packoffset-element, it must have a value of x or r.

For example

cbuffer MyConstants float2 Pos : packoffset(c1.z); ;

The Pos shader constant will be located at byte offset in the constant buffer MyConstants.

9.5.4 Default Constant Buffer[Resources.cnbuf.defcb]

All variables declarations in the global scope are implicitly added to default constant buffer called $Globals, unless they are marked static, groupshared, or declare a resource or array of resources.

Layout rules for a default constant buffer are the same as for a named cbuffer declaration group.

Default constant buffer declarations can have an optional resource-binding annotation with a register-type c or C added before their ; terminal. This annotation does not define a virtual register binding but rather an index into an array of 16-byte rows that represents the default constant buffer, similar to the packoffset annotation.

For example

float4 CameraPos : register(c2);

is equivalent to

cbuffer CB float4 CameraPos : packoffset(c2);

9.6 Samplers[Resources.samp]

9.7 CheckAccessFullyMapped[Resources.mapcheck]

The mapped status value returned by certain texture and buffer methods can be intrepreted by a built-in function:

bool CheckAccessFullyMapped(in uint status);

This function returns true if the value was accessed from a fully committed resource, or from fully mapped pages of a sparse resource. If any part of the return value was from unmapped memory, false is returned.

9.8 Resource Binding[Resources.binding]

Resources are bound to external memory using virtual registers within logical registers spaces. These can be specified explicitly using attributes after the global resource declaration or implicitly by leaving them off.

resource-binding:
: register( register-type bind-number )
: register( register-type bind-number , space bind-number )
register-type: one of
t u b s c T U B S C
bind-number:
digit
bind-number digit

The register type indicates whether the binding is for a read-only (t/T), a writable (u/U), a constant buffer (b/B), or a sampler (s/S). The register bind number indicates the register number at which the resource variable begins. The optional second parameter indicates the virtual register space that the register belongs to.

Register type c/C defines layout information for the default constant buffer (9.5.4).

Sample syntax of virtual register binding attributes:

Buffer<float> robuf : register(t0, space0); RWBuffer<float> rwbuf : register(u0, space0); SamplerState samp : register(s0, space0); cbuffer cbuf : register(b0, space0) float f; ;

Each resource must have a unique register. Different resources cannot occupy the same register, but read-only and writable buffers have separate namespaces and different logical register spaces have independent sets of register numbers. Meaning the following is all allowed:

Buffer<float> mybuf : register(t0, space0); Buffer<float> yourbuf : register(t0, space1); RWBuffer<float> hisbuf : register(u0, space0); RWBuffer<float> herbuf : register(u0, space1);

An aggregate resource type can be:

  • a struct containing one or more resources types

  • an array of resource types

  • an array or struct containing either of the above

Aggregate resource types with register annotations occupy the first register they specify and however many additional sequential registers the aggregate requires to assign a register to each of its elements that correspond to the given register type. Multiple register annotations can be placed on aggregates involving structs where each corresponds to a distinct register type that will apply to all the registers of that type in the aggregate.

Resource types contained in structs are only allocated registers when they are explicitly used. This includes elements of arrays of resources since such array elements must be indexed with literals.

// Occupies t0, t1, and t2. Buffer<float> fbuf[3] : register(t0, space0); // Occupies registers t3 - t14. Buffer<int4> ibuf[4][3] : register(t3, space0); // Occupies registers t15 and u0. struct RWBuffer<int> rwbuf; Buffer buf; sbufs : register(t15) : register(u0); // Occupies registers t16 - t21. struct Buffer bufs[5]; Buffer buf; robufs : register(t16); // Occupies registers t22-24 and u1-u2 struct Buffer r; RWBuffer<int> w; bibufs[2] : register(t22) : register(u1);

If the register binding or register space is not specified, implicit values are used. Whenever not specified, the space defaults to space0.

Buffer<float2> buf1 : register(t0, space0); Buffer<float2> buf2 : register(t1); // defaults to space0

When the register is not specified, resources will recieve implementation-dependent register assignments.