From 05fa33575fc0da7445973caf5d6d8f7521c27039 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Sat, 14 Sep 2024 18:02:15 -0600 Subject: [PATCH 1/7] Add resource chapter documenting buffers and bindings This adds a resource chapter that documents typed and raw buffers including their methods and compatible operators along with short descriptions of their functionality. It also adds a description of binding annotations for all types. Stub sections are included for constant buffers and samplers, but no information is provided as yet. Fixes https://github.com/llvm/wg-hlsl/issues/55 Fixes https://github.com/llvm/wg-hlsl/issues/56 --- specs/language/expressions.tex | 6 +- specs/language/hlsl.tex | 1 + specs/language/resources.tex | 943 +++++++++++++++++++++++++++++++++ 3 files changed, 948 insertions(+), 2 deletions(-) create mode 100644 specs/language/resources.tex diff --git a/specs/language/expressions.tex b/specs/language/expressions.tex index 3678144a..667efdf3 100644 --- a/specs/language/expressions.tex +++ b/specs/language/expressions.tex @@ -161,8 +161,10 @@ \p A \textit{postfix-expression} followed by an expression in square brackets (\texttt{[ ]}) is a subscript expression. In an array subscript expression of -the form \texttt{E1[E2]}, \texttt{E1} must either be a variable of array of -\texttt{T[]}, or an object of type \texttt{T} where \texttt{T} provides an +the form \texttt{E1[E2]}, \texttt{E1} must either be a variable of array, +vector, matrix, typed buffer (\ref{Resources.tybuf}), or structured buffer +(\ref{Resources.stbufs}), with elements of type \texttt{T[]} or an +object of type \texttt{T} where \texttt{T} provides an overloaded implementation of \texttt{operator[]} (\ref{Overload}).\footnote{HLSL does not support the base address of a subscript operator being the expression inside the braces, which is valid in C and C++.} diff --git a/specs/language/hlsl.tex b/specs/language/hlsl.tex index 0e3c8230..0bd60feb 100644 --- a/specs/language/hlsl.tex +++ b/specs/language/hlsl.tex @@ -91,6 +91,7 @@ \input{statements} \input{declarations} \input{overloading} +\input{resources} \input{placeholders} % Declare placeholder references diff --git a/specs/language/resources.tex b/specs/language/resources.tex new file mode 100644 index 00000000..9a4ed363 --- /dev/null +++ b/specs/language/resources.tex @@ -0,0 +1,943 @@ +\Ch{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, and Samplers. +Buffer and Texture types can be read-only or writable. +Read-only buffers and textures types constitute Shader Resource Views (SRVs) of the external memory. +Writable buffers and textures types constitute Unordered Access Views (UAVs) of the external memory. + +\Sec{Typed Buffers}{Resources.tybuf} + +The typed buffer class template represents a resource whose format can be converted upon load. + +Template types can be any type that totals or can be padded to 16 bytes. + +All typed buffers can be read through subscript operators or Load methods. +Writable typed buffers can be written through subscript operators. + +Typed Buffers are declared with the built-in templates: + +Where \texttt{T} can be any arithmetic type \ref{Basic.types.arithmetic} +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. + +\Sec{Read-only Typed Buffers}{Resources.rotybufs} + +\begin{HLSL} +template + class Buffer { + Buffer(); + Buffer operator=(Buffer buf); + + void GetDimensions(out uint width); + + // element access + T operator[](uint pos); + T Load(in int pos); + T Load(in int pos, out uint status); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.rotybufs.ctrs} + +Buffers can be defined with explicit or implicit template parameter types. +\begin{HLSL} + Buffer buf1; + Buffer<> buf2; + Buffer buf3; +\end{HLSL} +Since \texttt{float4} is the default type, all of these definitions are equivalent. + +When defined at global scope, Buffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, Buffers represent local references +that can be associated with global buffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + Buffer gbuf; + void doit() { + Buffer lbuf = gbuf; + } +\end{HLSL} +Buffer operands to the assignment operator must have the same element type. + +\Sub{Dimensions}{Resources.rotybufs.dims} + +The size of a Buffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint size); +\end{HLSL} + +This returns the full size of the buffer in bytes through the \texttt{width} out parameter. + +\Sub{Element Access}{Resources.rotybufs.access} + +The contents of Buffers can be retrieved using the \texttt{Load} methods +or the subscript operator. + +\begin{HLSL} + T Load(in int pos); + T operator[](uint pos); +\end{HLSL} + +These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. + +An additional \texttt{Load} method returns the indicated element just as the other, +but also takes a second \texttt{status} parameter that returns information about the accessed resource. +\begin{HLSL} + T Load(in int pos, out uint status); +\end{HLSL} + +The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile +resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped +tile resource and false otherwise. If tiled resourced are not enabled, it will return true. + +\Sec{Writable Typed Buffers}{Resources.rwtybufs} + +\begin{HLSL} +template + class RWBuffer { + + RWBuffer(); + RWBuffer operator=(RWBuffer buf); + + void GetDimensions(out uint size); + + // element access + T operator[](uint n); + T Load(in int pos); + T Load(in int pos, out uint status); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.rwtybufs.ctrs} + +RWBuffers must be defined with explicit template parameter types. +\begin{HLSL} + RWBuffer buf; +\end{HLSL} + +When defined at global scope, RWBuffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, RWBuffers represent local references +that can be associated with global buffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + RWBuffer gbuf; + void doit() { + RWBuffer lbuf = gbuf; + } +\end{HLSL} +RWBuffer operands to the assignment operator must have the same element type. + +\Sub{Dimensions}{Resources.rwtybufs.dims} + +The size of a RWBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint size); +\end{HLSL} + +This returns the full size of the buffer in bytes through the \texttt{width} out parameter. + +\Sub{Element Access}{Resources.rwtybufs.access} + +The contents of RWBuffers can be retrieved using the \texttt{Load} methods +or the subscript operator. + +\begin{HLSL} + T Load(in int pos); + T operator[](uint pos); +\end{HLSL} + +These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. + +An additional \texttt{Load} method returns the indicated element just as the other, +but also takes a second \texttt{status} parameter that returns information about the accessed resource. +\begin{HLSL} + T Load(in int pos, out uint status); +\end{HLSL} + +The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile +resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped +tile resource and false otherwise. If tiled resourced are not enabled, it will return true. + +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. +\begin{HLSL} + T &operator[](uint pos); +\end{HLSL} + +\Sec{Raw Buffer Types}{Resources.rawbufs} + +Raw buffers 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. + +but partial writes aren't allowed. +Though structured buffers can contain vectors, +assignment to individual vector elements will result in an error. +I HAVE BEEN UNABLE TO VERIFY THIS, THOUGH I WAS SURE IT WAS TRUE! + +\Sec{Read-only Byte Access Buffers}{Resources.robabufs} + +\begin{HLSL} + class ByteAddressBuffer { + + ByteAddressBuffer(); + ByteAddressBuffer operator=(ByteAddressBuffer buf); + + void GetDimensions(out uint size); + + // element access + uint Load(in uint byteOffset) + uint2 Load2(in uint byteOffset) + uint3 Load3(in uint byteOffset) + uint4 Load4(in uint byteOffset) + template + T Load(in uint byteOffset); + + uint Load(in uint byteOffset, out uint status) + uint2 Load2(in uint byteOffset, out uint status) + uint3 Load3(in uint byteOffset, out uint status) + uint4 Load4(in uint byteOffset, out uint status) + template + T Load(in uint byteOffset, out uint status); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.robabufs.ctrs} + +Since their contents are viewed as raw bytes, ByteAddressBuffers are defined as a simple variable definition. +\begin{HLSL} + ByteAddressBuffer buf; +\end{HLSL} + +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. + +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. + +\begin{HLSL} + ByteAddressBuffer gbuf; + void doit(bool b) { + ByteAddressBuffer lbuf = gbuf; + } +\end{HLSL} + +\Sub{Dimensions}{Resources.robabufs.dims} + +The size of a ByteAddressBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint size); +\end{HLSL} + +This returns the full size of the buffer in bytes through the \texttt{width} out parameter. + +\Sub{Element Access}{Resources.robabufs.access} + +The contents of ByteAddressBuffers can be retrieved using the \texttt{Load} methods. + +\begin{HLSL} + uint Load(in uint byteOffset) + uint2 Load2(in uint byteOffset) + uint3 Load3(in uint byteOffset) + uint4 Load4(in uint byteOffset) +\end{HLSL} + +These each return the bytes at the given position \texttt{byteOffset} in the form of one or more unsigned integers. +The \texttt{byteOffset} address is in bytes and 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. + +\begin{HLSL} + template + T Load(in uint byteOffset); +\end{HLSL} + +The alignment requirements of \texttt{byteOffset} for this operation is the size in bytes of the largest +scalar type contained in the given tyep \texttt{T}. + +Additional \texttt{Load} methods return the same values as the others, +but also take a second \texttt{status} parameter that returns information about the accessed resource. +\begin{HLSL} + uint Load(in uint byteOffset, out uint status) + uint2 Load2(in uint byteOffset, out uint status) + uint3 Load3(in uint byteOffset, out uint status) + uint4 Load4(in uint byteOffset, out uint status) + template + T Load(in uint byteOffset, out uint status); +\end{HLSL} + +The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile +resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped +tile resource and false otherwise. If tiled resourced are not enabled, it will return true. + +\Sec{Writable Byte Access Buffers}{Resources.rwbabufs} + +\begin{HLSL} + class RWByteAddressBuffer { + + RWByteAddressBuffer(); + RWByteAddressBuffer operator=(RWByteAddressBuffer buf); + + void GetDimensions(out uint size); + + // element access + uint Load(in uint byteOffset) + uint2 Load2(in uint byteOffset) + uint3 Load3(in uint byteOffset) + uint4 Load4(in uint byteOffset) + template + T Load(in uint byteOffset); + + uint Load(in uint byteOffset, out uint status) + uint2 Load2(in uint byteOffset, out uint status) + uint3 Load3(in uint byteOffset, out uint status) + uint4 Load4(in uint byteOffset, out uint status) + template + T Load(in uint byteOffset, out uint status); + + void Store(in uint byteOffset, in uint value) + void Store2(in uint byteOffset, in uint2 value) + void Store3(in uint byteOffset, in uint3 value) + void Store4(in uint byteOffset, in uint4 value) + + template + void Store(in uint byteOffset, in T value) + + // 32-bit integer atomic arithmetic/bitwise operations + void InterlockedAdd(in uint pos, in uint value); + void InterlockedAdd(in uint pos, in uint value, out uint original) + void InterlockedAnd(in uint pos, in uint value); + void InterlockedAnd(in uint pos, in uint value, out uint original) + void InterlockedOr(in uint pos, in uint value); + void InterlockedOr(in uint pos, in uint value, out uint original) + void InterlockedXor(in uint pos, in uint value); + void InterlockedXor(in uint pos, in uint value, out uint original) + + // 32-bit integer atomic comparison operations + void InterlockedMin(in uint pos, in int value) + void InterlockedMin(in uint pos, in uint value) + void InterlockedMin(in uint pos, in int value, out int original) + void InterlockedMin(in uint pos, in uint value, out uint original) + void InterlockedMax(in uint pos, in int value) + void InterlockedMax(in uint pos, in uint value) + void InterlockedMax(in uint pos, in int value, out int original) + void InterlockedMax(in uint pos, in uint value, out uint original) + + // 32-bit integer atomic compare/exchange operations + void InterlockedCompareStore(in uint pos, in uint compare, in uint value); + void InterlockedExchange(in uint pos, in uint value, out uint original); + void InterlockedCompareExchange(in uint pos, in uint compare, in uint value, + out uint original); + + // 64-bit integer atomic arithmatic/bitwise operations + void InterlockedAdd64(in uint pos, in uint64_t value); + void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedAnd64(in uint pos, in uint64_t value); + void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedOr64(in uint pos, in uint64_t value); + void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedXor64(in uint pos, in uint64_t value); + void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t original) + + // 64-bit integer atomic comparison operations + void InterlockedMin64(in uint pos, in int64_t value) + void InterlockedMin64(in uint pos, in int64_t value, out int64_t original) + void InterlockedMin64(in uint pos, in uint64_t value) + void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedMax64(in uint pos, in int64_t value) + void InterlockedMax64(in uint pos, in int64_t value, out int64_t original) + void InterlockedMax64(in uint pos, in uint64_t value) + void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original) + + // 64-bit integer atomic compare/exchange operations + void InterlockedCompareStore64(in uint pos, in uint64_t compare, in uint64_t value); + void InterlockedExchange64(in uint pos, in int64_t value, out int64_t original); + void InterlockedCompareExchange64(in uint pos, 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); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.rwbabufs.ctrs} + +Since their contents are viewed as raw bytes, RWByteAddressBuffers are defined as a simple variable definition. +\begin{HLSL} + RWByteAddressBuffer buf; +\end{HLSL} + +When defined at global scope, RWByteAccessBuffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, RWByteAccessBuffers represent local references +that can be associated with global RWByteAccessBuffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + RWByteAddressBuffer gbuf; + void doit(bool b) { + RWByteAddressBuffer lbuf = gbuf; + } +\end{HLSL} + +\Sub{Dimensions}{Resources.rwbabufs.dims} + +The size of a RWByteAddressBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint size); +\end{HLSL} + +This returns the full size of the buffer in bytes through the \texttt{width} out parameter. + +\Sub{Element Access}{Resources.rwbabufs.access} + +The contents of RWByteAccessBuffers can be retrieved using the \texttt{Load} methods. + +\begin{HLSL} + uint Load(in uint byteOffset) + uint2 Load2(in uint byteOffset) + uint3 Load3(in uint byteOffset) + uint4 Load4(in uint byteOffset) +\end{HLSL} + +These each return the bytes at the given position \texttt{byteOffset} in the form of one or more unsigned integers. +The \texttt{byteOffset} address is in bytes and 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. + +\begin{HLSL} + template + T Load(in uint byteOffset); +\end{HLSL} + +The alignment requirements of \texttt{byteOffset} for this operation is the size in bytes of the largest +scalar type contained in the given tyep \texttt{T}. + +Additional \texttt{Load} methods return the same values as the others, +but also take a second \texttt{status} parameter that returns information about the accessed resource. +\begin{HLSL} + uint Load(in uint byteOffset, out uint status) + uint2 Load2(in uint byteOffset, out uint status) + uint3 Load3(in uint byteOffset, out uint status) + uint4 Load4(in uint byteOffset, out uint status) + template + T Load(in uint byteOffset, out uint status); +\end{HLSL} + +The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile +resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped +tile resource and false otherwise. If tiled resourced are not enabled, it will return true. + + +\Sub{Atomic Operations}{Resources.rwbabufs.atomics} + +RWByteAddressBuffers have a suite of atomic methods that perform the given operation +on signed or unsigned integer element data indexed by the given integer size +in a way that ensures no contention from other threads performing other operations. +Each has an overload that optionally returns the original value before the atomic operation was performed. + +\begin{HLSL} + void InterlockedAdd(in uint pos, in uint value); + void InterlockedAdd(in uint pos, in uint value, out uint original) + void InterlockedAnd(in uint pos, in uint value); + void InterlockedAnd(in uint pos, in uint value, out uint original) + void InterlockedOr(in uint pos, in uint value); + void InterlockedOr(in uint pos, in uint value, out uint original) + void InterlockedXor(in uint pos, in uint value); + void InterlockedXor(in uint pos, in uint value, out uint original) +\end{HLSL} + +Performs atomic addition, bitwise and, bitwise or, or bitwise exclusive or +on the element found in 32-bit integer position \texttt{pos} and the provided \texttt{value} +and stores the resulting sum in that buffer position, +optionally returning the orignal value of the buffer position through \texttt{original} + +\begin{HLSL} + void InterlockedMin(in uint pos, in int value) + void InterlockedMin(in uint pos, in uint value) + void InterlockedMin(in uint pos, in int value, out int original) + void InterlockedMin(in uint pos, in uint value, out uint original) + void InterlockedMax(in uint pos, in int value) + void InterlockedMax(in uint pos, in uint value) + void InterlockedMax(in uint pos, in int value, out int original) + void InterlockedMax(in uint pos, in uint value, out uint original) +\end{HLSL} + +Performs the sign-approrpriate minimum or maximum comparison of the 32-bit integer indexed by \texttt{pos} +and the provided \texttt{value} and assigns the less or greater as appropriate to that buffer position, +optionally returning the orignal value at that buffer position through \texttt{original} + +\begin{HLSL} + void InterlockedExchange(in uint pos, in uint value, out uint original); +\end{HLSL} + +Performs an atomic exchange of the the 32-bit integer indexed by \texttt{pos} with +the value of \texttt{value} and returns the original value at that position through \texttt{original}. + +\begin{HLSL} + void InterlockedCompareStore(in uint pos, in uint compare, in uint value); + void InterlockedCompareExchange(in uint pos, in uint compare, in uint value, + out uint original); +\end{HLSL} + +These perform an atomic exchange of or store to the the 32-bit integer indexed by \texttt{pos} +with the provided \texttt{value} if the value at that position matches the value of \texttt{compare}. +\texttt{InterlockedCompareExchange} returns the original value at that position through \texttt{original}. + +\begin{HLSL} + void InterlockedAdd64(in uint pos, in uint64_t value); + void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedAnd64(in uint pos, in uint64_t value); + void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedOr64(in uint pos, in uint64_t value); + void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedXor64(in uint pos, in uint64_t value); + void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t original) +\end{HLSL} + +Performs atomic addition, bitwise and, bitwise or, or bitwise exclusive or +on the element found in 64-bit integer position \texttt{pos} and the provided \texttt{value} +and stores the resulting sum in that buffer position, +optionally returning the orignal value of the buffer position through \texttt{original} + +\begin{HLSL} + void InterlockedMin64(in uint pos, in int64_t value) + void InterlockedMin64(in uint pos, in uint64_t value) + void InterlockedMin64(in uint pos, in int64_t value, out int64_t original) + void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedMax64(in uint pos, in int64_t value) + void InterlockedMax64(in uint pos, in uint64_t value) + void InterlockedMax64(in uint pos, in int64_t value, out int64_t original) + void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original) +\end{HLSL} + +Performs the sign-approrpriate minimum or maximum comparison of the 64-bit integer indexed by \texttt{pos} +and the provided \texttt{value} and assigns the less or greater as appropriate to that buffer position, +optionally returning the orignal value at that buffer position through \texttt{original} + +\begin{HLSL} + void InterlockedExchange64(in uint pos, in uint64_t value, out uint64_t original); +\end{HLSL} + +Performs an atomic exchange of the the 64-bit integer indexed by \texttt{pos} with +the value of \texttt{value} and returns the original value at that position through \texttt{original}. + +\begin{HLSL} + void InterlockedCompareStore64(in uint pos, in uint64_t compare, + in uint64_t value); + void InterlockedCompareExchange64(in uint pos, in uint64_t compare, + in uint64_t value, out uint64_t original); +\end{HLSL} + +These perform an atomic exchange of or store to the the 64-bit integer indexed by \texttt{pos} +with the provided \texttt{value} if the value at that position matches the value of \texttt{compare}. +\texttt{InterlockedCompareExchange64} returns the original value at that position through \texttt{original}. + +\begin{HLSL} + void InterlockedExchangeFloat(in uint byteOffest, in float value, + out float original); +\end{HLSL} + +Performs an atomic exchange of the the 32-bit float indexed by \texttt{pos} with +the value of \texttt{value} and returns the original value at that position through \texttt{original}. + +\begin{HLSL} + 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); +\end{HLSL} + +These perform an atomic exchange of or store to the the 32-bit float indexed by \texttt{pos} +with the provided \texttt{value} if the value at that position matches the value of \texttt{compare} +in a bitwise comparison. +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. +\texttt{InterlockedCompareExchangeFloatBitwise} returns the original value at that position through \texttt{original}. + +\Sec{Structured Buffers}{Resources.stbufs} + +StructuredBuffers 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 and the casting to the given types is done bit for bit. +StructuredBuffers can be defined with scalar, vector, matrix, or user-defined struct elements. + +\Sec{Read-only Structured Buffers}{Resources.rostbufs} + +\begin{HLSL} +template + class StructuredBuffer { + StructuredBuffer(); + StructuredBuffer operator=(StructuredBuffer buf); + + void GetDimensions(out uint count, out uint stride); + + // element access + T operator[](uint pos); + T Load(in int pos); + T Load(in int pos, out uint status); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.rostbufs.ctrs} + +StructuredBuffers must be defined with explicit template parameter types. +\begin{HLSL} + struct S {int i; float f;}; + StructuredBuffer buf1; + StructuredBuffer buf2; + StructuredBuffer buf3; +\end{HLSL} + +When defined at global scope, StructuredBuffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, StructuredBuffers represent local references +that can be associated with global buffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + StructuredBuffer gbuf; + void doit() { + StructuredBuffer lbuf = gbuf; + } +\end{HLSL} +StructuredBuffer operands to the assignment operator must have the same element type. + +\Sub{Dimensions}{Resources.rostbufs.dims} + +The structure count and stride of a StructuredBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint count, out uint stride); +\end{HLSL} + +This returns number of structured elements of the buffer through the \texttt{count} out parameter +and the size of each element in bytes through the \texttt{stride} out parameter. + +\Sub{Element Access}{Resources.rostbufs.access} + +The contents of StructuredBuffers can be retrieved using the \texttt{Load} methods +or the subscript operator. + +\begin{HLSL} + T Load(in int pos); + T operator[](uint pos); +\end{HLSL} + +These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. + +An additional \texttt{Load} method returns the indicated element just as the other, +but also takes a second \texttt{status} parameter that returns information about the accessed resource. +\begin{HLSL} + T Load(in int pos, out uint status); +\end{HLSL} + +The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile +resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped +tile resource and false otherwise. If tiled resourced are not enabled, it will return true. + +\Sec{Writable Structured Buffers}{Resources.rwstbufs} + +\begin{HLSL} +template + class RWStructuredBuffer { + RWStructuredBuffer(); + RWStructuredBuffer operator=(RWStructuredBuffer buf); + + void GetDimensions(out uint count, out uint stride); + + // element access + T operator[](uint pos); + T Load(in int pos); + T Load(in int pos, out uint status); + + // Hidden counter increment/decrement + uint IncrementCounter(); + uint DecrementCounter(); + +}; +\end{HLSL} + +\Sub{Constructors}{Resources.rwstbufs.ctrs} + +RWStructuredBuffers must be defined with explicit template parameter types. +\begin{HLSL} + struct S {int i; float f;}; + RWStructuredBuffer buf1; + RWStructuredBuffer buf2; + RWStructuredBuffer buf3; +\end{HLSL} + +When defined at global scope, RWStructuredBuffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, RWStructuredBuffers represent local references +that can be associated with global buffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + RWStructuredBuffer gbuf; + void doit() { + RWStructuredBuffer lbuf = gbuf; + } +\end{HLSL} +RWStructuredBuffer operands to the assignment operator must have the same element type. + +\Sub{Dimensions}{Resources.rwstbufs.dims} + +The structure count and stride of a RWStructuredBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint count, out uint stride); +\end{HLSL} + +This returns number of structured elements of the buffer through the \texttt{count} out parameter +and the size of each element in bytes through the \texttt{stride} out parameter. + +\Sub{Element Access}{Resources.rwstbufs.access} + +The contents of RWStructuredBuffers can be retrieved using the \texttt{Load} methods +or the subscript operator. + +\begin{HLSL} + T Load(in int pos); + T operator[](uint pos); +\end{HLSL} + +These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. + +An additional \texttt{Load} method returns the indicated element just as the other, +but also takes a second \texttt{status} parameter that returns information about the accessed resource. +\begin{HLSL} + T Load(in int pos, out uint status); +\end{HLSL} + +The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile +resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped +tile resource and false otherwise. If tiled resourced are not enabled, it will return true. + +\Sub{Counter Manipulation}{Resources.rwstbufs.counter} + +\begin{HLSL} + uint IncrementCounter(); + uint DecrementCounter(); +\end{HLSL} + +Increments or decrements the hidden counter associated with the RWStructuredbuffer. + +\Sec{AppendStructuredBuffer}{Resources.apstbufs} + +AppendStructuredBuffers are buffers that can only be appended to as an output stream. + +\begin{HLSL} +template + class AppendStructuredBuffer { + AppendStructuredBuffer(); + AppendStructuredBuffer operator=(AppendStructuredBuffer buf); + + void GetDimensions(out uint count, out uint stride); + + void Append(in T value); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.apstbufs.ctrs} + +AppendStructuredBuffers must be defined with explicit template parameter types. +\begin{HLSL} + struct S {int i; float f;}; + AppendStructuredBuffer buf1; + AppendStructuredBuffer buf2; + AppendStructuredBuffer buf3; +\end{HLSL} + +When defined at global scope, AppendStructuredBuffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, AppendStructuredBuffers represent local references +that can be associated with global buffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + AppendStructuredBuffer gbuf; + void doit() { + AppendStructuredBuffer lbuf = gbuf; + } +\end{HLSL} +AppendStructuredBuffer operands to the assignment operator must have the same element type. + +\Sub{Dimensions}{Resources.apstbufs.dims} + +The structure count and stride of a AppendStructuredBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint count, out uint stride); +\end{HLSL} + +This returns number of structured elements of the buffer through the \texttt{count} out parameter +and the size of each element in bytes through the \texttt{stride} out parameter. + +\Sub{Append}{Resources.apstbufs.append} + +\begin{HLSL} + void Append(in T value ) +\end{HLSL} + +Appends the \texttt{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. + +\Sec{ConsumeStructuredBuffer}{Resources.cnstbufs} + +ConsumeStructuredBuffers are buffers that can only have values pulled from them as an input stream. + +\begin{HLSL} +template + class ConsumeStructuredBuffer { + ConsumeStructuredBuffer(); + ConsumeStructuredBuffer operator=(ConsumeStructuredBuffer buf); + + void GetDimensions(out uint count, out uint stride); + + void Consume(); +}; +\end{HLSL} + +\Sub{Constructors}{Resources.cnstbufs.ctrs} + +ConsumeStructuredBuffers must be defined with explicit template parameter types. +\begin{HLSL} + struct S {int i; float f;}; + ConsumeStructuredBuffer buf1; + ConsumeStructuredBuffer buf2; + ConsumeStructuredBuffer buf3; +\end{HLSL} + +When defined at global scope, ConsumeStructuredBuffers are bound to externally-defined backing stores +using the explicit binding location if provided or the implicit binding if not. + +When defined at local scope, ConsumeStructuredBuffers represent local references +that can be associated with global buffers when assigned, +but must be resolvable to a unique global buffer. + +\begin{HLSL} + ConsumeStructuredBuffer gbuf; + void doit() { + ConsumeStructuredBuffer lbuf = gbuf; + } +\end{HLSL} +ConsumeStructuredBuffer operands to the assignment operator must have the same element type. + +\Sub{Dimensions}{Resources.cnstbufs.dims} + +The structure count and stride of a ConsumeStructuredBuffer can be retrieved using the \texttt{GetDimensions} method. +\begin{HLSL} +void GetDimensions(out uint count, out uint stride); +\end{HLSL} + +This returns number of structured elements of the buffer through the \texttt{count} out parameter +and the size of each element in bytes through the \texttt{stride} out parameter. + +\Sub{Consume}{Resources.cnstbufs.consume} + +\begin{HLSL} + void Consume(); +\end{HLSL} + +Removes and returns a value of the template parameter types from the end of the ConsumeStructuredBuffer. + +\Sec{Constant Buffers}{Resources.cnbuf} + +\Sec{Samplers}{Resources.samp} + + +\Sec{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. + +\begin{grammar} + \define{resource-binding}\br + \terminal{: register(} register-type bind-number \terminal{)}\br + \terminal{: register(} register-type bind-number , \terminal{space} bind-number \terminal{)}\br + + \define{register-type} \textnormal{one of}\br + \terminal{t u b s}\br + + \define{bind-number}\br + digit\br + bind-number digit\br +\end{grammar} + +The register type indicates whether the binding is for a read-only SRV (\texttt{t}), a writable UAV (\texttt{u}), +a constant buffer (\texttt{b}), or a sampler (\texttt{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. + +Sample syntax of virtual register binding attributes: +\begin{HLSL} + Buffer robuf : register(t0, space0); + RWBuffer rwbuf : register(u0, space0); + SamplerState samp : register(s0, space0); + cbuffer cbuf : register(b0, space0) { float f; }; +\end{HLSL} + +Each resource must have a unique register. Different resources cannot occupy the same register, +but SRVs and UAVs have separate namespaces and different logical register spaces have independent +sets of register numbers. Meaning the following is all allowed: +\begin{HLSL} + Buffer mybuf : register(t0, space0); + Buffer yourbuf : register(t0, space1); + RWBuffer hisbuf : register(u0, space0); + RWBuffer herbuf : register(u0, space1); +\end{HLSL} + +Resource arrays occupy the first register they specify as well as however many additional registers +the array requires to assign a register to each of its elements. + +\begin{HLSL} + Buffer fbuf[3] : register(t0, space0); // occupies t0, t1, and t2 + Buffer ibuf[4][3] : register(t3, space0); // occupies registers t3 - t15 +\end{HLSL} + +If the register binding or register space is not specified, implicit values are used. +Whenever not specified, the space defaults to \texttt{space0}. + +\begin{HLSL} + Buffer buf1 : register(t0, space0); + Buffer buf2 : register(t1); // defaults to space0 +\end{HLSL} + +When the register is not specified, resources will recieve implementation-dependent register assignments. From 5b147371fd2cfc9693a8c670c1b4a6e8f21df5e2 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Tue, 29 Oct 2024 17:26:58 -0600 Subject: [PATCH 2/7] Respond to feedback Strip mention of UAVs and SRVs Remove some legacy text mistakenly left in as notes, mischaracterization of tiled memory, leftover sentences from moved or deleted segments, and elements of code examples. Better summarize typed buffers upfront. Add description of UDT register annotations. --- specs/language/resources.tex | 57 +++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/specs/language/resources.tex b/specs/language/resources.tex index 9a4ed363..21c27d7d 100644 --- a/specs/language/resources.tex +++ b/specs/language/resources.tex @@ -4,20 +4,18 @@ These take the form of Typed Buffers, Raw Buffers, Textures, and Samplers. Buffer and Texture types can be read-only or writable. -Read-only buffers and textures types constitute Shader Resource Views (SRVs) of the external memory. -Writable buffers and textures types constitute Unordered Access Views (UAVs) of the external memory. \Sec{Typed Buffers}{Resources.tybuf} -The typed buffer class template represents a resource whose format can be converted upon load. +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. Template types can be any type that totals or can be padded to 16 bytes. All typed buffers can be read through subscript operators or Load methods. Writable typed buffers can be written through subscript operators. -Typed Buffers are declared with the built-in templates: - Where \texttt{T} can be any arithmetic type \ref{Basic.types.arithmetic} 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. @@ -74,7 +72,7 @@ void GetDimensions(out uint size); \end{HLSL} -This returns the full size of the buffer in bytes through the \texttt{width} out parameter. +This returns the full size of the buffer in bytes through the \texttt{size} out parameter. \Sub{Element Access}{Resources.rotybufs.access} @@ -95,7 +93,7 @@ \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. @@ -167,7 +165,7 @@ \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. @@ -179,15 +177,15 @@ \Sec{Raw Buffer Types}{Resources.rawbufs} -Raw buffers are either ByteAddressBuffers or StructuredBuffers. +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. -but partial writes aren't allowed. +Partial writes aren't allowed. Though structured buffers can contain vectors, assignment to individual vector elements will result in an error. -I HAVE BEEN UNABLE TO VERIFY THIS, THOUGH I WAS SURE IT WAS TRUE! \Sec{Read-only Byte Access Buffers}{Resources.robabufs} @@ -218,7 +216,7 @@ \Sub{Constructors}{Resources.robabufs.ctrs} -Since their contents are viewed as raw bytes, ByteAddressBuffers are defined as a simple variable definition. +Since their contents are viewed as raw bytes, ByteAddressBuffers are defined without any type parameters. \begin{HLSL} ByteAddressBuffer buf; \end{HLSL} @@ -232,7 +230,7 @@ \begin{HLSL} ByteAddressBuffer gbuf; - void doit(bool b) { + void doit() { ByteAddressBuffer lbuf = gbuf; } \end{HLSL} @@ -284,7 +282,7 @@ \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. @@ -401,7 +399,7 @@ \begin{HLSL} RWByteAddressBuffer gbuf; - void doit(bool b) { + void doit() { RWByteAddressBuffer lbuf = gbuf; } \end{HLSL} @@ -453,7 +451,7 @@ \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. @@ -665,7 +663,7 @@ \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. @@ -745,7 +743,7 @@ \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource on tile-based platforms. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} +resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. @@ -901,7 +899,7 @@ bind-number digit\br \end{grammar} -The register type indicates whether the binding is for a read-only SRV (\texttt{t}), a writable UAV (\texttt{u}), +The register type indicates whether the binding is for a read-only (\texttt{t}), a writable (\texttt{u}), a constant buffer (\texttt{b}), or a sampler (\texttt{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. @@ -915,7 +913,7 @@ \end{HLSL} Each resource must have a unique register. Different resources cannot occupy the same register, -but SRVs and UAVs have separate namespaces and different logical register spaces have independent +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: \begin{HLSL} Buffer mybuf : register(t0, space0); @@ -924,12 +922,23 @@ RWBuffer herbuf : register(u0, space1); \end{HLSL} -Resource arrays occupy the first register they specify as well as however many additional registers -the array requires to assign a register to each of its elements. +Resource aggregates structs containing multiple resources types or arrays of resource types or structs containing one or more resource types. +When aggregate types have register annotations, they occupy the first register they specify as well as 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. + +\begin{note} +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. +\end{note} \begin{HLSL} - Buffer fbuf[3] : register(t0, space0); // occupies t0, t1, and t2 - Buffer ibuf[4][3] : register(t3, space0); // occupies registers t3 - t15 + Buffer fbuf[3] : register(t0, space0); // Occupies t0, t1, and t2. + Buffer ibuf[4][3] : register(t3, space0); // Occupies registers t3 - t14. + struct {RWBuffer rwbuf; Buffer buf;} sbufs : register(t15) : register(u0); // Occupies registers t15 and u0. + struct {Buffer bufs[5]; Buffer buf;} robufs : register(t16); // Occupies registers t16 - t21. + struct {Buffer r; RWBuffer w;} bibufs[2] : register(t22) : register(u1); // Occupies registers t22-24 and u1-u2 \end{HLSL} If the register binding or register space is not specified, implicit values are used. From 4a39382dd4269d8514367d2fc1b6320c0697ddd0 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Thu, 31 Oct 2024 16:46:43 -0600 Subject: [PATCH 3/7] respond to feedback consolidate typed, byte-address, and structured buffers into common sections sharing documentation of their common elements and using inheritance and variant-specific sections to describe differences. Make const all methods that should be Add copy constructors to all buffer types. Revise expressions changes. --- specs/language/expressions.tex | 10 +- specs/language/resources.tex | 764 +++++++++++---------------------- 2 files changed, 266 insertions(+), 508 deletions(-) diff --git a/specs/language/expressions.tex b/specs/language/expressions.tex index 667efdf3..3f94dc1f 100644 --- a/specs/language/expressions.tex +++ b/specs/language/expressions.tex @@ -162,12 +162,10 @@ \p A \textit{postfix-expression} followed by an expression in square brackets (\texttt{[ ]}) is a subscript expression. In an array subscript expression of the form \texttt{E1[E2]}, \texttt{E1} must either be a variable of array, -vector, matrix, typed buffer (\ref{Resources.tybuf}), or structured buffer -(\ref{Resources.stbufs}), with elements of type \texttt{T[]} or an -object of type \texttt{T} where \texttt{T} provides an -overloaded implementation of \texttt{operator[]} (\ref{Overload}).\footnote{HLSL -does not support the base address of a subscript operator being the expression -inside the braces, which is valid in C and C++.} +vector, or matrix of \texttt{T[]}, or an object of type \texttt{T} where +\texttt{T} provides an overloaded implementation of \texttt{operator[]} +(\ref{Overload}).\footnote{HLSL does not support the base address of a subscript +operator being the expression inside the braces, which is valid in C and C++.} \Sec{Function Calls}{Expr.Post.Call} diff --git a/specs/language/resources.tex b/specs/language/resources.tex index 21c27d7d..87baaa61 100644 --- a/specs/language/resources.tex +++ b/specs/language/resources.tex @@ -23,137 +23,87 @@ Typed buffers perform format conversions on load such that the underlying data gets converted to the destination type. -\Sec{Read-only Typed Buffers}{Resources.rotybufs} +\Sec{Typed Buffers}{Resources.tybufs} \begin{HLSL} template class Buffer { + public: Buffer(); + Buffer(Buffer buf); Buffer operator=(Buffer buf); - void GetDimensions(out uint width); + void GetDimensions(out uint width) const; - // element access - T operator[](uint pos); - T Load(in int pos); - T Load(in int pos, out uint status); + // Element access. + T operator[](uint pos) const; + T Load(in int pos) const; + T Load(in int pos, out uint status) const; }; -\end{HLSL} - -\Sub{Constructors}{Resources.rotybufs.ctrs} - -Buffers can be defined with explicit or implicit template parameter types. -\begin{HLSL} - Buffer buf1; - Buffer<> buf2; - Buffer buf3; -\end{HLSL} -Since \texttt{float4} is the default type, all of these definitions are equivalent. - -When defined at global scope, Buffers are bound to externally-defined backing stores -using the explicit binding location if provided or the implicit binding if not. - -When defined at local scope, Buffers represent local references -that can be associated with global buffers when assigned, -but must be resolvable to a unique global buffer. - -\begin{HLSL} - Buffer gbuf; - void doit() { - Buffer lbuf = gbuf; - } -\end{HLSL} -Buffer operands to the assignment operator must have the same element type. - -\Sub{Dimensions}{Resources.rotybufs.dims} - -The size of a Buffer can be retrieved using the \texttt{GetDimensions} method. -\begin{HLSL} -void GetDimensions(out uint size); -\end{HLSL} - -This returns the full size of the buffer in bytes through the \texttt{size} out parameter. - -\Sub{Element Access}{Resources.rotybufs.access} - -The contents of Buffers can be retrieved using the \texttt{Load} methods -or the subscript operator. - -\begin{HLSL} - T Load(in int pos); - T operator[](uint pos); -\end{HLSL} - -These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. - -An additional \texttt{Load} method returns the indicated element just as the other, -but also takes a second \texttt{status} parameter that returns information about the accessed resource. -\begin{HLSL} - T Load(in int pos, out uint status); -\end{HLSL} - -The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} -built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped -tile resource and false otherwise. If tiled resourced are not enabled, it will return true. -\Sec{Writable Typed Buffers}{Resources.rwtybufs} -\begin{HLSL} template - class RWBuffer { - + class RWBuffer : public Buffer { + public: RWBuffer(); + RWBuffer(RWBuffer buf); RWBuffer operator=(RWBuffer buf); - void GetDimensions(out uint size); - // element access - T operator[](uint n); - T Load(in int pos); - T Load(in int pos, out uint status); + T &operator[](uint n); }; +} \end{HLSL} -\Sub{Constructors}{Resources.rwtybufs.ctrs} +\Sub{Constructors}{Resources.tybufs.ctrs} + +Read-only Buffers can be defined with explicit or implicit template parameter types. +\begin{HLSL} + Buffer buf1; + Buffer<> buf2; + Buffer buf3; +\end{HLSL} +Since \texttt{float4} is the default type, all of these definitions are equivalent. RWBuffers must be defined with explicit template parameter types. \begin{HLSL} RWBuffer buf; \end{HLSL} -When defined at global scope, RWBuffers are bound to externally-defined backing stores +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. -When defined at local scope, RWBuffers represent local references +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. \begin{HLSL} - RWBuffer gbuf; - void doit() { - RWBuffer lbuf = gbuf; + Buffer grobuf; + RWBuffer grwbuf; + void main() { + Buffer lrobuf = grobuf; + RWBuffer lrwbuf = grwbuf; } \end{HLSL} -RWBuffer operands to the assignment operator must have the same element type. +Buffer operands to the assignment operator must have the same element type. -\Sub{Dimensions}{Resources.rwtybufs.dims} +\Sub{Dimensions}{Resources.tybufs.dims} -The size of a RWBuffer can be retrieved using the \texttt{GetDimensions} method. +The size of a typed buffer can be retrieved using the \texttt{GetDimensions} method. \begin{HLSL} -void GetDimensions(out uint size); +void GetDimensions(out uint width) const; \end{HLSL} -This returns the full size of the buffer in bytes through the \texttt{width} out parameter. +This returns the full legnth, in elements of the buffer through the \texttt{width} out parameter. -\Sub{Element Access}{Resources.rwtybufs.access} +\Sub{Element Access}{Resources.tybufs.access} -The contents of RWBuffers can be retrieved using the \texttt{Load} methods +The contents of typed buffers can be retrieved using the \texttt{Load} methods or the subscript operator. \begin{HLSL} - T Load(in int pos); - T operator[](uint pos); + T Load(in int pos) const; + T operator[](uint pos) const; \end{HLSL} These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. @@ -161,7 +111,7 @@ An additional \texttt{Load} method returns the indicated element just as the other, but also takes a second \texttt{status} parameter that returns information about the accessed resource. \begin{HLSL} - T Load(in int pos, out uint status); + T Load(in int pos, out uint status) const; \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile @@ -175,6 +125,9 @@ T &operator[](uint pos); \end{HLSL} +Partial writes aren't allowed. +Assignment to individual vector elements will result in an error. + \Sec{Raw Buffer Types}{Resources.rawbufs} Raw buffers are one-dimensional resources of arbitrary memory layout. @@ -183,161 +136,66 @@ StructuredBuffers have an associated structure type that determines how they are indexed. This type can be a scalar, vector, matrix, or user-defined struct. -Partial writes aren't allowed. -Though structured buffers can contain vectors, -assignment to individual vector elements will result in an error. - -\Sec{Read-only Byte Access Buffers}{Resources.robabufs} +\Sec{Byte Access Buffers}{Resources.babufs} \begin{HLSL} class ByteAddressBuffer { - + public: ByteAddressBuffer(); + ByteAddressBuffer(ByteAddressBuffer buf); ByteAddressBuffer operator=(ByteAddressBuffer buf); - void GetDimensions(out uint size); + void GetDimensions(out uint size) const; - // element access - uint Load(in uint byteOffset) - uint2 Load2(in uint byteOffset) - uint3 Load3(in uint byteOffset) - uint4 Load4(in uint byteOffset) + // Element access. + uint Load(in uint byteOffset) const; + uint2 Load2(in uint byteOffset) const; + uint3 Load3(in uint byteOffset) const; + uint4 Load4(in uint byteOffset) const; template - T Load(in uint byteOffset); + T Load(in uint byteOffset) const; - uint Load(in uint byteOffset, out uint status) - uint2 Load2(in uint byteOffset, out uint status) - uint3 Load3(in uint byteOffset, out uint status) - uint4 Load4(in uint byteOffset, out uint status) + uint Load(in uint byteOffset, out uint status) const; + uint2 Load2(in uint byteOffset, out uint status) const; + uint3 Load3(in uint byteOffset, out uint status) const; + uint4 Load4(in uint byteOffset, out uint status) const; template - T Load(in uint byteOffset, out uint status); + T Load(in uint byteOffset, out uint status) const; }; -\end{HLSL} - -\Sub{Constructors}{Resources.robabufs.ctrs} - -Since their contents are viewed as raw bytes, ByteAddressBuffers are defined without any type parameters. -\begin{HLSL} - ByteAddressBuffer buf; -\end{HLSL} - -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. - -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. - -\begin{HLSL} - ByteAddressBuffer gbuf; - void doit() { - ByteAddressBuffer lbuf = gbuf; - } -\end{HLSL} - -\Sub{Dimensions}{Resources.robabufs.dims} - -The size of a ByteAddressBuffer can be retrieved using the \texttt{GetDimensions} method. -\begin{HLSL} -void GetDimensions(out uint size); -\end{HLSL} - -This returns the full size of the buffer in bytes through the \texttt{width} out parameter. - -\Sub{Element Access}{Resources.robabufs.access} - -The contents of ByteAddressBuffers can be retrieved using the \texttt{Load} methods. - -\begin{HLSL} - uint Load(in uint byteOffset) - uint2 Load2(in uint byteOffset) - uint3 Load3(in uint byteOffset) - uint4 Load4(in uint byteOffset) -\end{HLSL} - -These each return the bytes at the given position \texttt{byteOffset} in the form of one or more unsigned integers. -The \texttt{byteOffset} address is in bytes and 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. - -\begin{HLSL} - template - T Load(in uint byteOffset); -\end{HLSL} - -The alignment requirements of \texttt{byteOffset} for this operation is the size in bytes of the largest -scalar type contained in the given tyep \texttt{T}. - -Additional \texttt{Load} methods return the same values as the others, -but also take a second \texttt{status} parameter that returns information about the accessed resource. -\begin{HLSL} - uint Load(in uint byteOffset, out uint status) - uint2 Load2(in uint byteOffset, out uint status) - uint3 Load3(in uint byteOffset, out uint status) - uint4 Load4(in uint byteOffset, out uint status) - template - T Load(in uint byteOffset, out uint status); -\end{HLSL} - -The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} -built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped -tile resource and false otherwise. If tiled resourced are not enabled, it will return true. - -\Sec{Writable Byte Access Buffers}{Resources.rwbabufs} - -\begin{HLSL} - class RWByteAddressBuffer { + class RWByteAddressBuffer : public ByteAddressBuffer { + public: RWByteAddressBuffer(); + RWByteAddressBuffer(RWByteAddressBuffer buf); RWByteAddressBuffer operator=(RWByteAddressBuffer buf); - void GetDimensions(out uint size); - - // element access - uint Load(in uint byteOffset) - uint2 Load2(in uint byteOffset) - uint3 Load3(in uint byteOffset) - uint4 Load4(in uint byteOffset) - template - T Load(in uint byteOffset); - - uint Load(in uint byteOffset, out uint status) - uint2 Load2(in uint byteOffset, out uint status) - uint3 Load3(in uint byteOffset, out uint status) - uint4 Load4(in uint byteOffset, out uint status) + // Element assignment. + void Store(in uint byteOffset, in uint value); + void Store2(in uint byteOffset, in uint2 value); + void Store3(in uint byteOffset, in uint3 value); + void Store4(in uint byteOffset, in uint4 value); template - T Load(in uint byteOffset, out uint status); + void Store(in uint byteOffset, in T value); - void Store(in uint byteOffset, in uint value) - void Store2(in uint byteOffset, in uint2 value) - void Store3(in uint byteOffset, in uint3 value) - void Store4(in uint byteOffset, in uint4 value) - - template - void Store(in uint byteOffset, in T value) - - // 32-bit integer atomic arithmetic/bitwise operations + // 32-bit integer atomic arithmetic/bitwise operations. void InterlockedAdd(in uint pos, in uint value); - void InterlockedAdd(in uint pos, in uint value, out uint original) + void InterlockedAdd(in uint pos, in uint value, out uint original); void InterlockedAnd(in uint pos, in uint value); - void InterlockedAnd(in uint pos, in uint value, out uint original) + void InterlockedAnd(in uint pos, in uint value, out uint original); void InterlockedOr(in uint pos, in uint value); - void InterlockedOr(in uint pos, in uint value, out uint original) + void InterlockedOr(in uint pos, in uint value, out uint original); void InterlockedXor(in uint pos, in uint value); - void InterlockedXor(in uint pos, in uint value, out uint original) + void InterlockedXor(in uint pos, in uint value, out uint original); // 32-bit integer atomic comparison operations - void InterlockedMin(in uint pos, in int value) - void InterlockedMin(in uint pos, in uint value) - void InterlockedMin(in uint pos, in int value, out int original) - void InterlockedMin(in uint pos, in uint value, out uint original) - void InterlockedMax(in uint pos, in int value) - void InterlockedMax(in uint pos, in uint value) - void InterlockedMax(in uint pos, in int value, out int original) - void InterlockedMax(in uint pos, in uint value, out uint original) + void InterlockedMin(in uint pos, in int value); + void InterlockedMin(in uint pos, in uint value); + void InterlockedMin(in uint pos, in int value, out int original); + void InterlockedMin(in uint pos, in uint value, out uint original); + void InterlockedMax(in uint pos, in int value); + void InterlockedMax(in uint pos, in uint value); + void InterlockedMax(in uint pos, in int value, out int original); + void InterlockedMax(in uint pos, in uint value, out uint original); // 32-bit integer atomic compare/exchange operations void InterlockedCompareStore(in uint pos, in uint compare, in uint value); @@ -347,23 +205,23 @@ // 64-bit integer atomic arithmatic/bitwise operations void InterlockedAdd64(in uint pos, in uint64_t value); - void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original); void InterlockedAnd64(in uint pos, in uint64_t value); - void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original); void InterlockedOr64(in uint pos, in uint64_t value); - void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original); void InterlockedXor64(in uint pos, in uint64_t value); - void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t original); // 64-bit integer atomic comparison operations - void InterlockedMin64(in uint pos, in int64_t value) - void InterlockedMin64(in uint pos, in int64_t value, out int64_t original) - void InterlockedMin64(in uint pos, in uint64_t value) - void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original) - void InterlockedMax64(in uint pos, in int64_t value) - void InterlockedMax64(in uint pos, in int64_t value, out int64_t original) - void InterlockedMax64(in uint pos, in uint64_t value) - void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedMin64(in uint pos, in int64_t value); + void InterlockedMin64(in uint pos, in int64_t value, out int64_t original); + void InterlockedMin64(in uint pos, in uint64_t value); + void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original); + void InterlockedMax64(in uint pos, in int64_t value); + void InterlockedMax64(in uint pos, in int64_t value, out int64_t original); + void InterlockedMax64(in uint pos, in uint64_t value); + void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original); // 64-bit integer atomic compare/exchange operations void InterlockedCompareStore64(in uint pos, in uint64_t compare, in uint64_t value); @@ -383,45 +241,48 @@ }; \end{HLSL} -\Sub{Constructors}{Resources.rwbabufs.ctrs} +\Sub{Constructors}{Resources.babufs.ctrs} -Since their contents are viewed as raw bytes, RWByteAddressBuffers are defined as a simple variable definition. +Since their contents are viewed as raw bytes, ByteAddressBuffers are defined without any type parameters. \begin{HLSL} - RWByteAddressBuffer buf; + ByteAddressBuffer robuf; + RWByteAddressBuffer rwbuf; \end{HLSL} -When defined at global scope, RWByteAccessBuffers are bound to externally-defined backing stores +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. -When defined at local scope, RWByteAccessBuffers represent local references -that can be associated with global RWByteAccessBuffers when assigned, +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. \begin{HLSL} - RWByteAddressBuffer gbuf; - void doit() { - RWByteAddressBuffer lbuf = gbuf; + ByteAddressBuffer grobuf; + RWByteAddressBuffer grwbuf; + void main() { + ByteAddressBuffer lrobuf = grobuf; + RWByteAddressBuffer lrwbuf = grwbuf; } \end{HLSL} -\Sub{Dimensions}{Resources.rwbabufs.dims} +\Sub{Dimensions}{Resources.babufs.dims} -The size of a RWByteAddressBuffer can be retrieved using the \texttt{GetDimensions} method. +The size of a ByteAddressBuffer can be retrieved using the \texttt{GetDimensions} method. \begin{HLSL} -void GetDimensions(out uint size); +void GetDimensions(out uint size) const; \end{HLSL} -This returns the full size of the buffer in bytes through the \texttt{width} out parameter. +This returns the full size of the buffer in bytes through the \texttt{size} out parameter. -\Sub{Element Access}{Resources.rwbabufs.access} +\Sub{Element Access}{Resources.babufs.access} -The contents of RWByteAccessBuffers can be retrieved using the \texttt{Load} methods. +The contents of ByteAddressBuffers can be retrieved using the \texttt{Load} methods. \begin{HLSL} - uint Load(in uint byteOffset) - uint2 Load2(in uint byteOffset) - uint3 Load3(in uint byteOffset) - uint4 Load4(in uint byteOffset) + uint Load(in uint byteOffset) const; + uint2 Load2(in uint byteOffset) const; + uint3 Load3(in uint byteOffset) const; + uint4 Load4(in uint byteOffset) const; \end{HLSL} These each return the bytes at the given position \texttt{byteOffset} in the form of one or more unsigned integers. @@ -433,7 +294,7 @@ \begin{HLSL} template - T Load(in uint byteOffset); + T Load(in uint byteOffset) const; \end{HLSL} The alignment requirements of \texttt{byteOffset} for this operation is the size in bytes of the largest @@ -442,12 +303,12 @@ Additional \texttt{Load} methods return the same values as the others, but also take a second \texttt{status} parameter that returns information about the accessed resource. \begin{HLSL} - uint Load(in uint byteOffset, out uint status) - uint2 Load2(in uint byteOffset, out uint status) - uint3 Load3(in uint byteOffset, out uint status) - uint4 Load4(in uint byteOffset, out uint status) + uint Load(in uint byteOffset, out uint status) const; + uint2 Load2(in uint byteOffset, out uint status) const; + uint3 Load3(in uint byteOffset, out uint status) const; + uint4 Load4(in uint byteOffset, out uint status) const; template - T Load(in uint byteOffset, out uint status); + T Load(in uint byteOffset, out uint status) const; \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile @@ -455,8 +316,7 @@ built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. - -\Sub{Atomic Operations}{Resources.rwbabufs.atomics} +\Sub{Atomic Operations}{Resources.babufs.atomics} RWByteAddressBuffers have a suite of atomic methods that perform the given operation on signed or unsigned integer element data indexed by the given integer size @@ -465,32 +325,32 @@ \begin{HLSL} void InterlockedAdd(in uint pos, in uint value); - void InterlockedAdd(in uint pos, in uint value, out uint original) + void InterlockedAdd(in uint pos, in uint value, out uint original); void InterlockedAnd(in uint pos, in uint value); - void InterlockedAnd(in uint pos, in uint value, out uint original) + void InterlockedAnd(in uint pos, in uint value, out uint original); void InterlockedOr(in uint pos, in uint value); - void InterlockedOr(in uint pos, in uint value, out uint original) + void InterlockedOr(in uint pos, in uint value, out uint original); void InterlockedXor(in uint pos, in uint value); - void InterlockedXor(in uint pos, in uint value, out uint original) + void InterlockedXor(in uint pos, in uint value, out uint original); \end{HLSL} -Performs atomic addition, bitwise and, bitwise or, or bitwise exclusive or +Perform atomic addition, bitwise and, bitwise or, or bitwise exclusive or on the element found in 32-bit integer position \texttt{pos} and the provided \texttt{value} and stores the resulting sum in that buffer position, optionally returning the orignal value of the buffer position through \texttt{original} \begin{HLSL} - void InterlockedMin(in uint pos, in int value) - void InterlockedMin(in uint pos, in uint value) - void InterlockedMin(in uint pos, in int value, out int original) - void InterlockedMin(in uint pos, in uint value, out uint original) - void InterlockedMax(in uint pos, in int value) - void InterlockedMax(in uint pos, in uint value) - void InterlockedMax(in uint pos, in int value, out int original) - void InterlockedMax(in uint pos, in uint value, out uint original) + void InterlockedMin(in uint pos, in int value); + void InterlockedMin(in uint pos, in uint value); + void InterlockedMin(in uint pos, in int value, out int original); + void InterlockedMin(in uint pos, in uint value, out uint original); + void InterlockedMax(in uint pos, in int value); + void InterlockedMax(in uint pos, in uint value); + void InterlockedMax(in uint pos, in int value, out int original); + void InterlockedMax(in uint pos, in uint value, out uint original); \end{HLSL} -Performs the sign-approrpriate minimum or maximum comparison of the 32-bit integer indexed by \texttt{pos} +Perform the sign-approrpriate minimum or maximum comparison of the 32-bit integer indexed by \texttt{pos} and the provided \texttt{value} and assigns the less or greater as appropriate to that buffer position, optionally returning the orignal value at that buffer position through \texttt{original} @@ -507,19 +367,19 @@ out uint original); \end{HLSL} -These perform an atomic exchange of or store to the the 32-bit integer indexed by \texttt{pos} +Perform an atomic exchange of or store to the the 32-bit integer indexed by \texttt{pos} with the provided \texttt{value} if the value at that position matches the value of \texttt{compare}. \texttt{InterlockedCompareExchange} returns the original value at that position through \texttt{original}. \begin{HLSL} void InterlockedAdd64(in uint pos, in uint64_t value); - void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original); void InterlockedAnd64(in uint pos, in uint64_t value); - void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original); void InterlockedOr64(in uint pos, in uint64_t value); - void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original); void InterlockedXor64(in uint pos, in uint64_t value); - void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t original); \end{HLSL} Performs atomic addition, bitwise and, bitwise or, or bitwise exclusive or @@ -528,14 +388,14 @@ optionally returning the orignal value of the buffer position through \texttt{original} \begin{HLSL} - void InterlockedMin64(in uint pos, in int64_t value) - void InterlockedMin64(in uint pos, in uint64_t value) - void InterlockedMin64(in uint pos, in int64_t value, out int64_t original) - void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original) - void InterlockedMax64(in uint pos, in int64_t value) - void InterlockedMax64(in uint pos, in uint64_t value) - void InterlockedMax64(in uint pos, in int64_t value, out int64_t original) - void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original) + void InterlockedMin64(in uint pos, in int64_t value); + void InterlockedMin64(in uint pos, in uint64_t value); + void InterlockedMin64(in uint pos, in int64_t value, out int64_t original); + void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original); + void InterlockedMax64(in uint pos, in int64_t value); + void InterlockedMax64(in uint pos, in uint64_t value); + void InterlockedMax64(in uint pos, in int64_t value, out int64_t original); + void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original); \end{HLSL} Performs the sign-approrpriate minimum or maximum comparison of the 64-bit integer indexed by \texttt{pos} @@ -556,7 +416,7 @@ in uint64_t value, out uint64_t original); \end{HLSL} -These perform an atomic exchange of or store to the the 64-bit integer indexed by \texttt{pos} +Perform an atomic exchange of or store to the the 64-bit integer indexed by \texttt{pos} with the provided \texttt{value} if the value at that position matches the value of \texttt{compare}. \texttt{InterlockedCompareExchange64} returns the original value at that position through \texttt{original}. @@ -577,146 +437,134 @@ out float original); \end{HLSL} -These perform an atomic exchange of or store to the the 32-bit float indexed by \texttt{pos} -with the provided \texttt{value} if the value at that position matches the value of \texttt{compare} -in a bitwise comparison. -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. -\texttt{InterlockedCompareExchangeFloatBitwise} returns the original value at that position through \texttt{original}. +Perform an atomic exchange of or store to the the 32-bit float indexed by +\texttt{pos} with the provided \texttt{value} if the value at that position +matches the value of \texttt{compare} in a bitwise comparison. +\texttt{InterlockedCompareExchangeFloatBitwise} returns the original value at +that position through \texttt{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. \Sec{Structured Buffers}{Resources.stbufs} -StructuredBuffers are raw buffers with associated types that facilitate indexing. +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 and the casting to the given types is done bit for bit. -StructuredBuffers can be defined with scalar, vector, matrix, or user-defined struct elements. +The buffer contents is treated as raw data and the casting to the given types +is done bit for bit. +Structured buffers can be defined with scalar, vector, matrix, or user-defined +struct elements. -\Sec{Read-only Structured Buffers}{Resources.rostbufs} +\Sec{Structured Buffers}{Resources.stbufs} + +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. \begin{HLSL} template class StructuredBuffer { + public: StructuredBuffer(); + StructuredBuffer(StructuredBuffer buf); StructuredBuffer operator=(StructuredBuffer buf); - void GetDimensions(out uint count, out uint stride); + void GetDimensions(out uint count, out uint stride) const; - // element access - T operator[](uint pos); - T Load(in int pos); - T Load(in int pos, out uint status); + // Element access. + T operator[](uint pos) const; + T Load(in int pos) const; + T Load(in int pos, out uint status) const; }; -\end{HLSL} -\Sub{Constructors}{Resources.rostbufs.ctrs} - -StructuredBuffers must be defined with explicit template parameter types. -\begin{HLSL} - struct S {int i; float f;}; - StructuredBuffer buf1; - StructuredBuffer buf2; - StructuredBuffer buf3; -\end{HLSL} - -When defined at global scope, StructuredBuffers are bound to externally-defined backing stores -using the explicit binding location if provided or the implicit binding if not. - -When defined at local scope, StructuredBuffers represent local references -that can be associated with global buffers when assigned, -but must be resolvable to a unique global buffer. + class RWStructuredBuffer { + public: + RWStructuredBuffer(); + RWStructuredBuffer(RWStructuredBuffer buf); + RWStructuredBuffer operator=(RWStructuredBuffer buf); -\begin{HLSL} - StructuredBuffer gbuf; - void doit() { - StructuredBuffer lbuf = gbuf; - } -\end{HLSL} -StructuredBuffer operands to the assignment operator must have the same element type. + // Element assignment. + T &operator[](uint pos); -\Sub{Dimensions}{Resources.rostbufs.dims} + // Hidden counter increment/decrement. + uint IncrementCounter(); + uint DecrementCounter(); +}; -The structure count and stride of a StructuredBuffer can be retrieved using the \texttt{GetDimensions} method. -\begin{HLSL} -void GetDimensions(out uint count, out uint stride); -\end{HLSL} +template + class AppendStructuredBuffer { + AppendStructuredBuffer(); + AppendStructuredBuffer(AppendStructuredBuffer buf); + AppendStructuredBuffer operator=(AppendStructuredBuffer buf); -This returns number of structured elements of the buffer through the \texttt{count} out parameter -and the size of each element in bytes through the \texttt{stride} out parameter. + void GetDimensions(out uint count, out uint stride) const; -\Sub{Element Access}{Resources.rostbufs.access} + void Append(in T value); +}; -The contents of StructuredBuffers can be retrieved using the \texttt{Load} methods -or the subscript operator. +template + class ConsumeStructuredBuffer { + ConsumeStructuredBuffer(); + ConsumeStructuredBuffer(ConsumeStructuredBuffer buf); + ConsumeStructuredBuffer operator=(ConsumeStructuredBuffer buf); -\begin{HLSL} - T Load(in int pos); - T operator[](uint pos); -\end{HLSL} + void GetDimensions(out uint count, out uint stride) const; -These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. + void Consume(); +}; -An additional \texttt{Load} method returns the indicated element just as the other, -but also takes a second \texttt{status} parameter that returns information about the accessed resource. -\begin{HLSL} - T Load(in int pos, out uint status); \end{HLSL} -The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} -built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped -tile resource and false otherwise. If tiled resourced are not enabled, it will return true. - -\Sec{Writable Structured Buffers}{Resources.rwstbufs} +\Sub{Constructors}{Resources.stbufs.ctrs} +Structured buffers must be defined with explicit template parameter types. \begin{HLSL} -template - class RWStructuredBuffer { - RWStructuredBuffer(); - RWStructuredBuffer operator=(RWStructuredBuffer buf); - - void GetDimensions(out uint count, out uint stride); - - // element access - T operator[](uint pos); - T Load(in int pos); - T Load(in int pos, out uint status); + struct S {int i; float f;}; + StructuredBuffer robuf1; + StructuredBuffer robuf2; + StructuredBuffer robuf3; - // Hidden counter increment/decrement - uint IncrementCounter(); - uint DecrementCounter(); + RWStructuredBuffer rwbuf1; + RWStructuredBuffer rwbuf2; + RWStructuredBuffer rwbuf3; -}; -\end{HLSL} - -\Sub{Constructors}{Resources.rwstbufs.ctrs} + AppendStructuredBuffer apbuf1; + AppendStructuredBuffer apbuf2; + AppendStructuredBuffer apbuf3; -RWStructuredBuffers must be defined with explicit template parameter types. -\begin{HLSL} - struct S {int i; float f;}; - RWStructuredBuffer buf1; - RWStructuredBuffer buf2; - RWStructuredBuffer buf3; + ConsumeStructuredBuffer cobuf1; + ConsumeStructuredBuffer cobuf2; + ConsumeStructuredBuffer cobuf3; \end{HLSL} -When defined at global scope, RWStructuredBuffers are bound to externally-defined backing stores +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. -When defined at local scope, RWStructuredBuffers represent local references +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. \begin{HLSL} - RWStructuredBuffer gbuf; - void doit() { - RWStructuredBuffer lbuf = gbuf; + StructuredBuffer grobuf; + RWStructuredBuffer grwbuf; + AppendStructuredBuffer gapbuf; + ConsumeStructuredBuffer gcobuf; + void main() { + StructuredBuffer lrobuf = grobuf; + RWStructuredBuffer lrwbuf = grwbuf; + AppendStructuredBuffer lbuf = gapbuf; + ConsumeStructuredBuffer lcobuf = gcobuf; } \end{HLSL} -RWStructuredBuffer operands to the assignment operator must have the same element type. +Structured buffer operands to the assignment operator must have the same element type. -\Sub{Dimensions}{Resources.rwstbufs.dims} +\Sub{Dimensions}{Resources.stbufs.dims} -The structure count and stride of a RWStructuredBuffer can be retrieved using the \texttt{GetDimensions} method. +The structure count and stride of a structured buffer can be retrieved using the \texttt{GetDimensions} method. \begin{HLSL} void GetDimensions(out uint count, out uint stride); \end{HLSL} @@ -724,14 +572,14 @@ This returns number of structured elements of the buffer through the \texttt{count} out parameter and the size of each element in bytes through the \texttt{stride} out parameter. -\Sub{Element Access}{Resources.rwstbufs.access} +\Sub{Element Access}{Resources.stbufs.access} -The contents of RWStructuredBuffers can be retrieved using the \texttt{Load} methods -or the subscript operator. +The contents of read-only StructuredBuffers and writable RWStructuredBuffers can be retrieved +using the \texttt{Load} methods or the subscript operator. \begin{HLSL} - T Load(in int pos); - T operator[](uint pos); + T Load(in int pos) const; + T operator[](uint pos) const; \end{HLSL} These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. @@ -739,7 +587,7 @@ An additional \texttt{Load} method returns the indicated element just as the other, but also takes a second \texttt{status} parameter that returns information about the accessed resource. \begin{HLSL} - T Load(in int pos, out uint status); + T Load(in int pos, out uint status) const; \end{HLSL} The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile @@ -747,128 +595,38 @@ built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped tile resource and false otherwise. If tiled resourced are not enabled, it will return true. -\Sub{Counter Manipulation}{Resources.rwstbufs.counter} - -\begin{HLSL} - uint IncrementCounter(); - uint DecrementCounter(); -\end{HLSL} - -Increments or decrements the hidden counter associated with the RWStructuredbuffer. - -\Sec{AppendStructuredBuffer}{Resources.apstbufs} - -AppendStructuredBuffers are buffers that can only be appended to as an output stream. - +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. \begin{HLSL} -template - class AppendStructuredBuffer { - AppendStructuredBuffer(); - AppendStructuredBuffer operator=(AppendStructuredBuffer buf); - - void GetDimensions(out uint count, out uint stride); - - void Append(in T value); -}; + T &operator[](uint pos); \end{HLSL} -\Sub{Constructors}{Resources.apstbufs.ctrs} +\Sub{Counter Manipulation}{Resources.stbufs.counter} -AppendStructuredBuffers must be defined with explicit template parameter types. -\begin{HLSL} - struct S {int i; float f;}; - AppendStructuredBuffer buf1; - AppendStructuredBuffer buf2; - AppendStructuredBuffer buf3; -\end{HLSL} - -When defined at global scope, AppendStructuredBuffers are bound to externally-defined backing stores -using the explicit binding location if provided or the implicit binding if not. - -When defined at local scope, AppendStructuredBuffers represent local references -that can be associated with global buffers when assigned, -but must be resolvable to a unique global buffer. +RWStructuredBuffers may have a hidden counter that can be incremented and decremented using methods. \begin{HLSL} - AppendStructuredBuffer gbuf; - void doit() { - AppendStructuredBuffer lbuf = gbuf; - } + uint IncrementCounter(); + uint DecrementCounter(); \end{HLSL} -AppendStructuredBuffer operands to the assignment operator must have the same element type. -\Sub{Dimensions}{Resources.apstbufs.dims} +Increment or decrements the hidden counter associated with the RWStructuredBuffer. -The structure count and stride of a AppendStructuredBuffer can be retrieved using the \texttt{GetDimensions} method. -\begin{HLSL} -void GetDimensions(out uint count, out uint stride); -\end{HLSL} +\Sub{Append}{Resources.stbufs.append} -This returns number of structured elements of the buffer through the \texttt{count} out parameter -and the size of each element in bytes through the \texttt{stride} out parameter. - -\Sub{Append}{Resources.apstbufs.append} +AppendStructuredBuffers can only be appended to as an output stream. \begin{HLSL} - void Append(in T value ) + void Append(in T value); \end{HLSL} Appends the \texttt{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. -\Sec{ConsumeStructuredBuffer}{Resources.cnstbufs} - -ConsumeStructuredBuffers are buffers that can only have values pulled from them as an input stream. - -\begin{HLSL} -template - class ConsumeStructuredBuffer { - ConsumeStructuredBuffer(); - ConsumeStructuredBuffer operator=(ConsumeStructuredBuffer buf); - - void GetDimensions(out uint count, out uint stride); - - void Consume(); -}; -\end{HLSL} - -\Sub{Constructors}{Resources.cnstbufs.ctrs} - -ConsumeStructuredBuffers must be defined with explicit template parameter types. -\begin{HLSL} - struct S {int i; float f;}; - ConsumeStructuredBuffer buf1; - ConsumeStructuredBuffer buf2; - ConsumeStructuredBuffer buf3; -\end{HLSL} - -When defined at global scope, ConsumeStructuredBuffers are bound to externally-defined backing stores -using the explicit binding location if provided or the implicit binding if not. - -When defined at local scope, ConsumeStructuredBuffers represent local references -that can be associated with global buffers when assigned, -but must be resolvable to a unique global buffer. - -\begin{HLSL} - ConsumeStructuredBuffer gbuf; - void doit() { - ConsumeStructuredBuffer lbuf = gbuf; - } -\end{HLSL} -ConsumeStructuredBuffer operands to the assignment operator must have the same element type. - -\Sub{Dimensions}{Resources.cnstbufs.dims} - -The structure count and stride of a ConsumeStructuredBuffer can be retrieved using the \texttt{GetDimensions} method. -\begin{HLSL} -void GetDimensions(out uint count, out uint stride); -\end{HLSL} - -This returns number of structured elements of the buffer through the \texttt{count} out parameter -and the size of each element in bytes through the \texttt{stride} out parameter. - \Sub{Consume}{Resources.cnstbufs.consume} +ConsumeStructuredBuffers can only have values pulled from them as an input stream. + \begin{HLSL} void Consume(); \end{HLSL} @@ -879,7 +637,6 @@ \Sec{Samplers}{Resources.samp} - \Sec{Resource Binding}{Resources.binding} Resources are bound to external memory using virtual registers within logical registers spaces. @@ -890,10 +647,8 @@ \define{resource-binding}\br \terminal{: register(} register-type bind-number \terminal{)}\br \terminal{: register(} register-type bind-number , \terminal{space} bind-number \terminal{)}\br - \define{register-type} \textnormal{one of}\br \terminal{t u b s}\br - \define{bind-number}\br digit\br bind-number digit\br @@ -934,11 +689,16 @@ \end{note} \begin{HLSL} - Buffer fbuf[3] : register(t0, space0); // Occupies t0, t1, and t2. - Buffer ibuf[4][3] : register(t3, space0); // Occupies registers t3 - t14. - struct {RWBuffer rwbuf; Buffer buf;} sbufs : register(t15) : register(u0); // Occupies registers t15 and u0. - struct {Buffer bufs[5]; Buffer buf;} robufs : register(t16); // Occupies registers t16 - t21. - struct {Buffer r; RWBuffer w;} bibufs[2] : register(t22) : register(u1); // Occupies registers t22-24 and u1-u2 + // Occupies t0, t1, and t2. + Buffer fbuf[3] : register(t0, space0); + // Occupies registers t3 - t14. + Buffer ibuf[4][3] : register(t3, space0); + // Occupies registers t15 and u0. + struct {RWBuffer 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 w;} bibufs[2] : register(t22) : register(u1); \end{HLSL} If the register binding or register space is not specified, implicit values are used. From 706242f9cb39431a67f39490e80a59e81a2513b2 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Fri, 1 Nov 2024 16:14:21 -0600 Subject: [PATCH 4/7] correct typos, refine CheckAccessFullyMapped In response to Damyan's comments Corrected some mistaken syntax in buffer declarations. Revise the description of CheckAccessFullyMapped, giving it its own section that other parts refer to. correct sign of parameters to the subscript operator --- specs/language/resources.tex | 64 +++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/specs/language/resources.tex b/specs/language/resources.tex index 87baaa61..648ea214 100644 --- a/specs/language/resources.tex +++ b/specs/language/resources.tex @@ -36,7 +36,7 @@ void GetDimensions(out uint width) const; // Element access. - T operator[](uint pos) const; + T operator[](int pos) const; T Load(in int pos) const; T Load(in int pos, out uint status) const; }; @@ -50,7 +50,7 @@ RWBuffer operator=(RWBuffer buf); // element access - T &operator[](uint n); + T &operator[](int n); }; } \end{HLSL} @@ -81,8 +81,8 @@ Buffer grobuf; RWBuffer grwbuf; void main() { - Buffer lrobuf = grobuf; - RWBuffer lrwbuf = grwbuf; + Buffer lrobuf = grobuf; + RWBuffer lrwbuf = grwbuf; } \end{HLSL} Buffer operands to the assignment operator must have the same element type. @@ -103,7 +103,7 @@ \begin{HLSL} T Load(in int pos) const; - T operator[](uint pos) const; + T operator[](int pos) const; \end{HLSL} These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. @@ -114,15 +114,15 @@ T Load(in int pos, out uint status) const; \end{HLSL} -The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} -built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped -tile resource and false otherwise. If tiled resourced are not enabled, it will return true. +The \texttt{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 \texttt{CheckAccessFullyMapped} (\ref{Resources.mapcheck}) +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. \begin{HLSL} - T &operator[](uint pos); + T &operator[](int pos); \end{HLSL} Partial writes aren't allowed. @@ -311,10 +311,10 @@ T Load(in uint byteOffset, out uint status) const; \end{HLSL} -The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} -built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped -tile resource and false otherwise. If tiled resourced are not enabled, it will return true. +The \texttt{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 \texttt{CheckAccessFullyMapped} (\ref{Resources.mapcheck}) +in order to interpret it. \Sub{Atomic Operations}{Resources.babufs.atomics} @@ -476,7 +476,7 @@ void GetDimensions(out uint count, out uint stride) const; // Element access. - T operator[](uint pos) const; + T operator[](int pos) const; T Load(in int pos) const; T Load(in int pos, out uint status) const; }; @@ -488,7 +488,7 @@ RWStructuredBuffer operator=(RWStructuredBuffer buf); // Element assignment. - T &operator[](uint pos); + T &operator[](int pos); // Hidden counter increment/decrement. uint IncrementCounter(); @@ -554,10 +554,10 @@ AppendStructuredBuffer gapbuf; ConsumeStructuredBuffer gcobuf; void main() { - StructuredBuffer lrobuf = grobuf; - RWStructuredBuffer lrwbuf = grwbuf; - AppendStructuredBuffer lbuf = gapbuf; - ConsumeStructuredBuffer lcobuf = gcobuf; + StructuredBuffer lrobuf = grobuf; + RWStructuredBuffer lrwbuf = grwbuf; + AppendStructuredBuffer lbuf = gapbuf; + ConsumeStructuredBuffer lcobuf = gcobuf; } \end{HLSL} Structured buffer operands to the assignment operator must have the same element type. @@ -579,7 +579,7 @@ \begin{HLSL} T Load(in int pos) const; - T operator[](uint pos) const; + T operator[](int pos) const; \end{HLSL} These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. @@ -590,15 +590,15 @@ T Load(in int pos, out uint status) const; \end{HLSL} -The \texttt{status} parameter returns an indication of whether the value retrieved accessed a mapped tile -resource. This parameter is interpretted using the \texttt{CheckAccessFullyMapped} -built-in function. If tiled resources are enabled, it returns true if the value was accessed from a mapped -tile resource and false otherwise. If tiled resourced are not enabled, it will return true. +The \texttt{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 \texttt{CheckAccessFullyMapped} (\ref{Resources.mapcheck}) +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. \begin{HLSL} - T &operator[](uint pos); + T &operator[](int pos); \end{HLSL} \Sub{Counter Manipulation}{Resources.stbufs.counter} @@ -637,6 +637,18 @@ \Sec{Samplers}{Resources.samp} +\Sec{CheckAccessFullyMapped}{Resources.mapcheck} + +The mapped status value returned by certain texture and buffer methods can be intrepreted by a built-in function: + +\begin{HLSL} + bool CheckAccessFullyMapped(in uint status); +\end{HLSL} + +This function returns true is 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. + \Sec{Resource Binding}{Resources.binding} Resources are bound to external memory using virtual registers within logical registers spaces. From d5604d8191e09feea13ec8e67a7940e5d33ae735 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Sat, 2 Nov 2024 11:50:50 -0600 Subject: [PATCH 5/7] Make headings more consistent, add binding section refs --- specs/language/resources.tex | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/specs/language/resources.tex b/specs/language/resources.tex index 648ea214..945736e6 100644 --- a/specs/language/resources.tex +++ b/specs/language/resources.tex @@ -5,7 +5,7 @@ These take the form of Typed Buffers, Raw Buffers, Textures, and Samplers. Buffer and Texture types can be read-only or writable. -\Sec{Typed Buffers}{Resources.tybuf} +\Sec{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 @@ -23,8 +23,6 @@ Typed buffers perform format conversions on load such that the underlying data gets converted to the destination type. -\Sec{Typed Buffers}{Resources.tybufs} - \begin{HLSL} template class Buffer { @@ -71,7 +69,7 @@ \end{HLSL} 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. +using the explicit binding location if provided or the implicit binding if not (\ref{Resources.binding}). When defined at local scope, typed buffers represent local references that can be associated with global buffers when assigned, @@ -128,7 +126,7 @@ Partial writes aren't allowed. Assignment to individual vector elements will result in an error. -\Sec{Raw Buffer Types}{Resources.rawbufs} +\Sec{Raw Buffers}{Resources.rawbufs} Raw buffers are one-dimensional resources of arbitrary memory layout. They are either ByteAddressBuffers or StructuredBuffers. @@ -250,7 +248,7 @@ \end{HLSL} 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. +using the explicit binding location if provided or the implicit binding if not (\ref{Resources.binding}). When defined at local scope, ByteAccessBuffers represent local references that can be associated with global ByteAccessBuffers when assigned, @@ -458,8 +456,6 @@ Structured buffers can be defined with scalar, vector, matrix, or user-defined struct elements. -\Sec{Structured Buffers}{Resources.stbufs} - 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. @@ -542,7 +538,7 @@ \end{HLSL} 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. +using the explicit binding location if provided or the implicit binding if not (\ref{Resources.binding}). When defined at local scope, structured buffers represent local references that can be associated with global buffers when assigned, From 93bbd1c5d9e9fa45d7c1af7cc8339f103ade8362 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Thu, 7 Nov 2024 13:40:18 -0700 Subject: [PATCH 6/7] Respond to Damyan's feedback Corrected a few parameter names and types This led to significant rewording of the atomic operation descriptions. Clarified unique global resource mapping. Refactored description of aggregate resource types for purposes of binding --- specs/language/resources.tex | 375 +++++++++++++++++++---------------- 1 file changed, 205 insertions(+), 170 deletions(-) diff --git a/specs/language/resources.tex b/specs/language/resources.tex index 945736e6..255905da 100644 --- a/specs/language/resources.tex +++ b/specs/language/resources.tex @@ -28,15 +28,15 @@ class Buffer { public: Buffer(); - Buffer(Buffer buf); + Buffer(Buffer &buf); Buffer operator=(Buffer buf); void GetDimensions(out uint width) const; // Element access. - T operator[](int pos) const; - T Load(in int pos) const; - T Load(in int pos, out uint status) const; + T operator[](int index) const; + T Load(in int index) const; + T Load(in int index, out uint status) const; }; @@ -73,7 +73,12 @@ 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. +but must be resolvable to a unique global buffer declaration. + +\begin{note} +Local buffers must be resolvable to a unique global declaration, but not necessarily a unique individual buffer. +Local buffer assignments can map to different resource array elements depending on runtime values. +\end{note} \begin{HLSL} Buffer grobuf; @@ -92,7 +97,7 @@ void GetDimensions(out uint width) const; \end{HLSL} -This returns the full legnth, in elements of the buffer through the \texttt{width} out parameter. +This returns the full length, in elements of the buffer through the \texttt{width} out parameter. \Sub{Element Access}{Resources.tybufs.access} @@ -100,16 +105,16 @@ or the subscript operator. \begin{HLSL} - T Load(in int pos) const; - T operator[](int pos) const; + T Load(in int index) const; + T operator[](int index) const; \end{HLSL} -These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. +These each return the element of the buffer's type at the given index \texttt{index}. An additional \texttt{Load} method returns the indicated element just as the other, but also takes a second \texttt{status} parameter that returns information about the accessed resource. \begin{HLSL} - T Load(in int pos, out uint status) const; + T Load(in int index, out uint status) const; \end{HLSL} The \texttt{status} parameter returns an indication of whether all of the retrieved value @@ -120,7 +125,7 @@ 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. \begin{HLSL} - T &operator[](int pos); + T &operator[](int index); \end{HLSL} Partial writes aren't allowed. @@ -140,91 +145,93 @@ class ByteAddressBuffer { public: ByteAddressBuffer(); - ByteAddressBuffer(ByteAddressBuffer buf); + ByteAddressBuffer(ByteAddressBuffer &buf); ByteAddressBuffer operator=(ByteAddressBuffer buf); void GetDimensions(out uint size) const; // Element access. - uint Load(in uint byteOffset) const; - uint2 Load2(in uint byteOffset) const; - uint3 Load3(in uint byteOffset) const; - uint4 Load4(in uint byteOffset) const; + 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 - T Load(in uint byteOffset) const; + T Load(in uint offset) const; - uint Load(in uint byteOffset, out uint status) const; - uint2 Load2(in uint byteOffset, out uint status) const; - uint3 Load3(in uint byteOffset, out uint status) const; - uint4 Load4(in uint byteOffset, out uint status) 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 - T Load(in uint byteOffset, out uint status) const; + T Load(in uint offset, out uint status) const; }; class RWByteAddressBuffer : public ByteAddressBuffer { public: RWByteAddressBuffer(); - RWByteAddressBuffer(RWByteAddressBuffer buf); + RWByteAddressBuffer(RWByteAddressBuffer &buf); RWByteAddressBuffer operator=(RWByteAddressBuffer buf); // Element assignment. - void Store(in uint byteOffset, in uint value); - void Store2(in uint byteOffset, in uint2 value); - void Store3(in uint byteOffset, in uint3 value); - void Store4(in uint byteOffset, in uint4 value); + 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 - void Store(in uint byteOffset, in T value); + void Store(in uint offset, in T value); // 32-bit integer atomic arithmetic/bitwise operations. - void InterlockedAdd(in uint pos, in uint value); - void InterlockedAdd(in uint pos, in uint value, out uint original); - void InterlockedAnd(in uint pos, in uint value); - void InterlockedAnd(in uint pos, in uint value, out uint original); - void InterlockedOr(in uint pos, in uint value); - void InterlockedOr(in uint pos, in uint value, out uint original); - void InterlockedXor(in uint pos, in uint value); - void InterlockedXor(in uint pos, in uint value, out uint original); + 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 pos, in int value); - void InterlockedMin(in uint pos, in uint value); - void InterlockedMin(in uint pos, in int value, out int original); - void InterlockedMin(in uint pos, in uint value, out uint original); - void InterlockedMax(in uint pos, in int value); - void InterlockedMax(in uint pos, in uint value); - void InterlockedMax(in uint pos, in int value, out int original); - void InterlockedMax(in uint pos, in uint value, out uint 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); // 32-bit integer atomic compare/exchange operations - void InterlockedCompareStore(in uint pos, in uint compare, in uint value); - void InterlockedExchange(in uint pos, in uint value, out uint original); - void InterlockedCompareExchange(in uint pos, in uint compare, in uint value, + 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 pos, in uint64_t value); - void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedAnd64(in uint pos, in uint64_t value); - void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedOr64(in uint pos, in uint64_t value); - void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedXor64(in uint pos, in uint64_t value); - void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t 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); // 64-bit integer atomic comparison operations - void InterlockedMin64(in uint pos, in int64_t value); - void InterlockedMin64(in uint pos, in int64_t value, out int64_t original); - void InterlockedMin64(in uint pos, in uint64_t value); - void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedMax64(in uint pos, in int64_t value); - void InterlockedMax64(in uint pos, in int64_t value, out int64_t original); - void InterlockedMax64(in uint pos, in uint64_t value); - void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t original); + 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 pos, in uint64_t compare, in uint64_t value); - void InterlockedExchange64(in uint pos, in int64_t value, out int64_t original); - void InterlockedCompareExchange64(in uint pos, in uint64_t compare, + 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 @@ -252,7 +259,7 @@ 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. +but must be resolvable to a unique global buffer declaration. \begin{HLSL} ByteAddressBuffer grobuf; @@ -277,14 +284,14 @@ The contents of ByteAddressBuffers can be retrieved using the \texttt{Load} methods. \begin{HLSL} - uint Load(in uint byteOffset) const; - uint2 Load2(in uint byteOffset) const; - uint3 Load3(in uint byteOffset) const; - uint4 Load4(in uint byteOffset) const; + uint Load(in uint offset) const; + uint2 Load2(in uint offset) const; + uint3 Load3(in uint offset) const; + uint4 Load4(in uint offset) const; \end{HLSL} -These each return the bytes at the given position \texttt{byteOffset} in the form of one or more unsigned integers. -The \texttt{byteOffset} address is in bytes and must be a multiple of 4. +These each return the bytes at the given byte offset into the buffer \texttt{offset} in the form of one or more unsigned integers. +The \texttt{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 @@ -292,21 +299,21 @@ \begin{HLSL} template - T Load(in uint byteOffset) const; + T Load(in uint offset) const; \end{HLSL} -The alignment requirements of \texttt{byteOffset} for this operation is the size in bytes of the largest +The alignment requirements of \texttt{offset} for this operation is the size in bytes of the largest scalar type contained in the given tyep \texttt{T}. Additional \texttt{Load} methods return the same values as the others, but also take a second \texttt{status} parameter that returns information about the accessed resource. \begin{HLSL} - uint Load(in uint byteOffset, out uint status) const; - uint2 Load2(in uint byteOffset, out uint status) const; - uint3 Load3(in uint byteOffset, out uint status) const; - uint4 Load4(in uint byteOffset, out uint status) 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 - T Load(in uint byteOffset, out uint status) const; + T Load(in uint offset, out uint status) const; \end{HLSL} The \texttt{status} parameter returns an indication of whether all of the retrieved value @@ -317,114 +324,127 @@ \Sub{Atomic Operations}{Resources.babufs.atomics} RWByteAddressBuffers have a suite of atomic methods that perform the given operation -on signed or unsigned integer element data indexed by the given integer size +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 has an overload that optionally returns the original value before the atomic operation was performed. +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. \begin{HLSL} - void InterlockedAdd(in uint pos, in uint value); - void InterlockedAdd(in uint pos, in uint value, out uint original); - void InterlockedAnd(in uint pos, in uint value); - void InterlockedAnd(in uint pos, in uint value, out uint original); - void InterlockedOr(in uint pos, in uint value); - void InterlockedOr(in uint pos, in uint value, out uint original); - void InterlockedXor(in uint pos, in uint value); - void InterlockedXor(in uint pos, in uint value, out uint original); + 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); \end{HLSL} -Perform atomic addition, bitwise and, bitwise or, or bitwise exclusive or -on the element found in 32-bit integer position \texttt{pos} and the provided \texttt{value} -and stores the resulting sum in that buffer position, -optionally returning the orignal value of the buffer position through \texttt{original} +Perform atomic addition, bitwise and, bitwise or, or bitwise exclusive or on +the 32-bit integer buffer value at the byte offset \texttt{offset} and the provided \texttt{value}. +Store the result to that offset buffer location, +optionally returning the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedMin(in uint pos, in int value); - void InterlockedMin(in uint pos, in uint value); - void InterlockedMin(in uint pos, in int value, out int original); - void InterlockedMin(in uint pos, in uint value, out uint original); - void InterlockedMax(in uint pos, in int value); - void InterlockedMax(in uint pos, in uint value); - void InterlockedMax(in uint pos, in int value, out int original); - void InterlockedMax(in uint pos, in uint value, out uint 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); \end{HLSL} -Perform the sign-approrpriate minimum or maximum comparison of the 32-bit integer indexed by \texttt{pos} -and the provided \texttt{value} and assigns the less or greater as appropriate to that buffer position, -optionally returning the orignal value at that buffer position through \texttt{original} +Perform the sign-approrpriate minimum or maximum comparison on +the 32-bit integer buffer value at the byte offset \texttt{offset} and the provided \texttt{value}. +Store the lesser or greater value, as appropriate, to that offset buffer location, +optionally returning the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedExchange(in uint pos, in uint value, out uint original); + void InterlockedExchange(in uint offset, in uint value, out uint original); \end{HLSL} -Performs an atomic exchange of the the 32-bit integer indexed by \texttt{pos} with -the value of \texttt{value} and returns the original value at that position through \texttt{original}. +Performs an atomic exchange of +the 32-bit integer buffer value at the byte offset \texttt{offset} with the provided \texttt{value}. +Stores \texttt{value} at the offset buffer location +and returns the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedCompareStore(in uint pos, in uint compare, in uint value); - void InterlockedCompareExchange(in uint pos, in uint compare, in uint value, + 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); \end{HLSL} -Perform an atomic exchange of or store to the the 32-bit integer indexed by \texttt{pos} -with the provided \texttt{value} if the value at that position matches the value of \texttt{compare}. -\texttt{InterlockedCompareExchange} returns the original value at that position through \texttt{original}. +Perform an atomic exchange of or store to +the 32-bit integer buffer value at the byte offset \texttt{offset} with the provided \texttt{value} +if the value at that location matches the value of \texttt{compare}. +\texttt{InterlockedCompareExchange} returns the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedAdd64(in uint pos, in uint64_t value); - void InterlockedAdd64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedAnd64(in uint pos, in uint64_t value); - void InterlockedAnd64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedOr64(in uint pos, in uint64_t value); - void InterlockedOr64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedXor64(in uint pos, in uint64_t value); - void InterlockedXor64(in uint pos, in uint64_t value, out uint64_t 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); \end{HLSL} -Performs atomic addition, bitwise and, bitwise or, or bitwise exclusive or -on the element found in 64-bit integer position \texttt{pos} and the provided \texttt{value} -and stores the resulting sum in that buffer position, -optionally returning the orignal value of the buffer position through \texttt{original} +Perform atomic addition, bitwise and, bitwise or, or bitwise exclusive or on +the 64-bit integer buffer value at the byte offset \texttt{offset} and the provided \texttt{value}. +Store the result to that offset buffer location, +optionally returning the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedMin64(in uint pos, in int64_t value); - void InterlockedMin64(in uint pos, in uint64_t value); - void InterlockedMin64(in uint pos, in int64_t value, out int64_t original); - void InterlockedMin64(in uint pos, in uint64_t value, out uint64_t original); - void InterlockedMax64(in uint pos, in int64_t value); - void InterlockedMax64(in uint pos, in uint64_t value); - void InterlockedMax64(in uint pos, in int64_t value, out int64_t original); - void InterlockedMax64(in uint pos, in uint64_t value, out uint64_t 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); \end{HLSL} -Performs the sign-approrpriate minimum or maximum comparison of the 64-bit integer indexed by \texttt{pos} -and the provided \texttt{value} and assigns the less or greater as appropriate to that buffer position, -optionally returning the orignal value at that buffer position through \texttt{original} +Perform the sign-approrpriate minimum or maximum comparison on +the 64-bit integer buffer value at the byte offset \texttt{offset} and the provided \texttt{value}. +Store the lesser or greater value, as appropriate, to that offset buffer location, +optionally returning the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedExchange64(in uint pos, in uint64_t value, out uint64_t original); + void InterlockedExchange64(in uint offset, in uint64_t value, out uint64_t original); \end{HLSL} -Performs an atomic exchange of the the 64-bit integer indexed by \texttt{pos} with -the value of \texttt{value} and returns the original value at that position through \texttt{original}. +Performs an atomic exchange of +the 64-bit integer buffer value at the byte offset \texttt{offset} with the provided \texttt{value}. +Stores \texttt{value} at the offset buffer location +and returns the original buffer value through \texttt{original}. \begin{HLSL} - void InterlockedCompareStore64(in uint pos, in uint64_t compare, + void InterlockedCompareStore64(in uint offset, in uint64_t compare, in uint64_t value); - void InterlockedCompareExchange64(in uint pos, in uint64_t compare, + void InterlockedCompareExchange64(in uint offset, in uint64_t compare, in uint64_t value, out uint64_t original); \end{HLSL} -Perform an atomic exchange of or store to the the 64-bit integer indexed by \texttt{pos} -with the provided \texttt{value} if the value at that position matches the value of \texttt{compare}. -\texttt{InterlockedCompareExchange64} returns the original value at that position through \texttt{original}. +Perform an atomic exchange of or store to +the 64-bit integer buffer value at the byte offset \texttt{offset} with the provided \texttt{value} +if the value at that location matches the value of \texttt{compare}. +\texttt{InterlockedCompareExchange} returns the original buffer value through \texttt{original}. \begin{HLSL} void InterlockedExchangeFloat(in uint byteOffest, in float value, out float original); \end{HLSL} -Performs an atomic exchange of the the 32-bit float indexed by \texttt{pos} with -the value of \texttt{value} and returns the original value at that position through \texttt{original}. +Performs an atomic exchange of +the 32-bit float buffer value at the byte offset \texttt{offset} with the provided \texttt{value}. +Stores \texttt{value} at the offset buffer location +and returns the original buffer value through \texttt{original}. + \begin{HLSL} void InterlockedCompareStoreFloatBitwise(in uint byteOffest, in float compare, @@ -435,11 +455,10 @@ out float original); \end{HLSL} -Perform an atomic exchange of or store to the the 32-bit float indexed by -\texttt{pos} with the provided \texttt{value} if the value at that position -matches the value of \texttt{compare} in a bitwise comparison. -\texttt{InterlockedCompareExchangeFloatBitwise} returns the original value at -that position through \texttt{original}. +Perform an atomic exchange of or store to +the 32-bit float buffer value at the byte offset \texttt{offset} with the provided \texttt{value} +if the value at that location matches the value of \texttt{compare} in a bitwise comparison. +\texttt{InterlockedCompareExchangeFloatBitwise} returns the original buffer value through \texttt{original}. Unlike standard floating point comparisons, values will only match if the bit representation matches which can miss some matching values that have different @@ -466,25 +485,26 @@ class StructuredBuffer { public: StructuredBuffer(); - StructuredBuffer(StructuredBuffer buf); + StructuredBuffer(StructuredBuffer &buf); StructuredBuffer operator=(StructuredBuffer buf); void GetDimensions(out uint count, out uint stride) const; // Element access. - T operator[](int pos) const; - T Load(in int pos) const; - T Load(in int pos, out uint status) const; + T operator[](int index) const; + T Load(in int index) const; + T Load(in int index, out uint status) const; }; - class RWStructuredBuffer { +template + class RWStructuredBuffer : public StructuredBuffer { public: RWStructuredBuffer(); - RWStructuredBuffer(RWStructuredBuffer buf); + RWStructuredBuffer(RWStructuredBuffer &buf); RWStructuredBuffer operator=(RWStructuredBuffer buf); // Element assignment. - T &operator[](int pos); + T &operator[](int index); // Hidden counter increment/decrement. uint IncrementCounter(); @@ -493,8 +513,9 @@ template class AppendStructuredBuffer { + public: AppendStructuredBuffer(); - AppendStructuredBuffer(AppendStructuredBuffer buf); + AppendStructuredBuffer(AppendStructuredBuffer &buf); AppendStructuredBuffer operator=(AppendStructuredBuffer buf); void GetDimensions(out uint count, out uint stride) const; @@ -504,13 +525,14 @@ template class ConsumeStructuredBuffer { + public: ConsumeStructuredBuffer(); - ConsumeStructuredBuffer(ConsumeStructuredBuffer buf); + ConsumeStructuredBuffer(ConsumeStructuredBuffer &buf); ConsumeStructuredBuffer operator=(ConsumeStructuredBuffer buf); void GetDimensions(out uint count, out uint stride) const; - void Consume(); + T Consume(); }; \end{HLSL} @@ -542,7 +564,13 @@ 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. +but must be resolvable to a unique global buffer declaration. + +\begin{note} +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. +\end{note} + \begin{HLSL} StructuredBuffer grobuf; @@ -574,16 +602,16 @@ using the \texttt{Load} methods or the subscript operator. \begin{HLSL} - T Load(in int pos) const; - T operator[](int pos) const; + T Load(in int index) const; + T operator[](int index) const; \end{HLSL} -These each return the element at the given position \texttt{pos} of the type specified in the buffer definition. +These each return the element of the buffer's type at the given index \texttt{index}. An additional \texttt{Load} method returns the indicated element just as the other, but also takes a second \texttt{status} parameter that returns information about the accessed resource. \begin{HLSL} - T Load(in int pos, out uint status) const; + T Load(in int index, out uint status) const; \end{HLSL} The \texttt{status} parameter returns an indication of whether all of the retrieved value @@ -594,7 +622,7 @@ 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. \begin{HLSL} - T &operator[](int pos); + T &operator[](int index); \end{HLSL} \Sub{Counter Manipulation}{Resources.stbufs.counter} @@ -624,7 +652,7 @@ ConsumeStructuredBuffers can only have values pulled from them as an input stream. \begin{HLSL} - void Consume(); + T Consume(); \end{HLSL} Removes and returns a value of the template parameter types from the end of the ConsumeStructuredBuffer. @@ -685,8 +713,15 @@ RWBuffer herbuf : register(u0, space1); \end{HLSL} -Resource aggregates structs containing multiple resources types or arrays of resource types or structs containing one or more resource types. -When aggregate types have register annotations, they occupy the first register they specify as well as however many additional sequential registers +A aggregate resource type can be: +\begin{itemize} +\item a struct containing one or more resources types +\item an array of resource types +\item an array or struct containing either of the above +\end{itemize} + +When aggregate resource types have register annotations, +they occupy the first register they specify as well as 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. From c5057b92399253d659f42c769e6f58bc93c557fd Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Mon, 25 Nov 2024 16:04:02 -0700 Subject: [PATCH 7/7] constify copy ctrs. Clarify grammar --- specs/language/resources.tex | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/specs/language/resources.tex b/specs/language/resources.tex index 255905da..42bc630a 100644 --- a/specs/language/resources.tex +++ b/specs/language/resources.tex @@ -28,7 +28,7 @@ class Buffer { public: Buffer(); - Buffer(Buffer &buf); + Buffer(const Buffer &buf); Buffer operator=(Buffer buf); void GetDimensions(out uint width) const; @@ -145,7 +145,7 @@ class ByteAddressBuffer { public: ByteAddressBuffer(); - ByteAddressBuffer(ByteAddressBuffer &buf); + ByteAddressBuffer(const ByteAddressBuffer &buf); ByteAddressBuffer operator=(ByteAddressBuffer buf); void GetDimensions(out uint size) const; @@ -169,7 +169,7 @@ class RWByteAddressBuffer : public ByteAddressBuffer { public: RWByteAddressBuffer(); - RWByteAddressBuffer(RWByteAddressBuffer &buf); + RWByteAddressBuffer(const RWByteAddressBuffer &buf); RWByteAddressBuffer operator=(RWByteAddressBuffer buf); // Element assignment. @@ -485,7 +485,7 @@ class StructuredBuffer { public: StructuredBuffer(); - StructuredBuffer(StructuredBuffer &buf); + StructuredBuffer(const StructuredBuffer &buf); StructuredBuffer operator=(StructuredBuffer buf); void GetDimensions(out uint count, out uint stride) const; @@ -500,7 +500,7 @@ class RWStructuredBuffer : public StructuredBuffer { public: RWStructuredBuffer(); - RWStructuredBuffer(RWStructuredBuffer &buf); + RWStructuredBuffer(const RWStructuredBuffer &buf); RWStructuredBuffer operator=(RWStructuredBuffer buf); // Element assignment. @@ -515,7 +515,7 @@ class AppendStructuredBuffer { public: AppendStructuredBuffer(); - AppendStructuredBuffer(AppendStructuredBuffer &buf); + AppendStructuredBuffer(const AppendStructuredBuffer &buf); AppendStructuredBuffer operator=(AppendStructuredBuffer buf); void GetDimensions(out uint count, out uint stride) const; @@ -527,7 +527,7 @@ class ConsumeStructuredBuffer { public: ConsumeStructuredBuffer(); - ConsumeStructuredBuffer(ConsumeStructuredBuffer &buf); + ConsumeStructuredBuffer(const ConsumeStructuredBuffer &buf); ConsumeStructuredBuffer operator=(ConsumeStructuredBuffer buf); void GetDimensions(out uint count, out uint stride) const; @@ -713,22 +713,22 @@ RWBuffer herbuf : register(u0, space1); \end{HLSL} -A aggregate resource type can be: +An aggregate resource type can be: \begin{itemize} \item a struct containing one or more resources types \item an array of resource types \item an array or struct containing either of the above \end{itemize} -When aggregate resource types have register annotations, -they occupy the first register they specify as well as however many additional sequential registers +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. \begin{note} 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. +This includes elements of arrays of resources since such array elements must be indexed with literals. \end{note} \begin{HLSL}