Skip to content

Commit 1ad02b7

Browse files
authored
Constant buffers language spec - initial draft (#419)
1 parent 767fa7f commit 1ad02b7

2 files changed

Lines changed: 251 additions & 13 deletions

File tree

specs/language/declarations.tex

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,25 @@
88

99
\define{declaration}\br
1010
\textit{name-declaration}\br
11-
\textit{special-declaration}
11+
\textit{special-declaration}\br
12+
\textit{empty-declaration}
1213

1314
\define{name-declaration}\br
15+
\textit{variable-declaration}\br
16+
\textit{function-declaration}\br
17+
\textit{namespace-declaration}\br
18+
\textit{record-declaration}\br
19+
\textit{template-declaration}\br
20+
\textit{type-alias-declaration}\br
1421
...
15-
22+
1623
\define{special-declaration}\br
1724
\textit{export-declaration-group}\br
25+
\textit{cbuffer-declaration-group}\br
1826
...
27+
28+
\define{empty-declaration} \terminal{;}
29+
1930
\end{grammar}
2031

2132
\Sec{Specifiers}{Decl.Spec}

specs/language/resources.tex

Lines changed: 238 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

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

5-
These take the form of Typed Buffers, Raw Buffers, Textures, and Samplers.
5+
These take the form of Typed Buffers, Raw Buffers, Textures, Constant Buffers and Samplers.
6+
67
Buffer and Texture types can be read-only or writable.
78

89
\Sec{Typed Buffers}{Resources.tybufs}
@@ -11,7 +12,8 @@
1112
Its contents are indexed by typed access to each element
1213
Types may have their formats converted upon load.
1314

14-
Template types can be any type that totals or can be padded to 16 bytes.
15+
The element type may be any type up to 16 bytes in size. Elements may be padded
16+
to 16 bytes if the element type is smaller than 16 bytes.
1517

1618
All typed buffers can be read through subscript operators or Load methods.
1719
Writable typed buffers can be written through subscript operators.
@@ -663,19 +665,239 @@
663665

664666
\Sec{Constant Buffers}{Resources.cnbuf}
665667

668+
Constant buffers represent resources that contain read-only constant data in a
669+
well-defined memory layout.
670+
671+
\Sub{Constant Buffer Declaration Block}{Resources.cnbuf.cb}
672+
673+
\p A constant buffer can be declared using the \texttt{cbuffer} specifier.
674+
675+
\begin{grammar}
676+
\define{cbuffer-declaration-group}\br
677+
\terminal{cbuffer} name \opt{resource-binding} \terminal{\{}
678+
\opt{cbuffer-declaration-seq} \terminal {\}}
679+
680+
\define{cbuffer-declaration-seq}\br
681+
\textit{cbuffer-declaration}\br
682+
\textit{cbuffer-declaration-seq cbuffer-declaration}
683+
684+
\define{cbuffer-declaration}\br
685+
\textit{variable-declaration}\br
686+
\textit{empty-declaration}
687+
\end{grammar}
688+
689+
\p The name of the \texttt{cbuffer} declaration group cannot be referenced from within the translation unit and is not required to be unique.
690+
691+
\p Variable declarations in the \texttt{cbuffer} declaration group are called \textit{shader constants}.
692+
693+
\p Shader constants can be referenced from anywhere in the translation unit after they are declared by directly using the declaration name. This implies that all shader constants declared in a translation unit must have unique names, even though they might be declared in different \texttt{cbuffer} declaration groups.
694+
695+
\p Variable declarations in the \texttt{cbuffer} declaration group cannot have \texttt{groupshared} or \texttt{static} variable modifiers.
696+
697+
\p Other declarations in the \texttt{cbuffer} declaration group such as
698+
\textit{namespace-declaration}, \textit{record-declaration} or
699+
\textit{function-declaration} are not allowed.
700+
701+
\p Nesting of \texttt{cbuffer} declaration groups is not allowed.
702+
703+
\p For example:
704+
705+
\begin{HLSL}
706+
cbuffer MyConstants {
707+
float4 CameraPos;
708+
};
709+
710+
float4 getCameraPosition() {
711+
return CameraPos;
712+
}
713+
\end{HLSL}
714+
715+
\Sub{Constant Buffer Class}{Resources.cnbuf.cbclass}
716+
717+
\p Another way of declaring constant buffers is by using the
718+
\texttt{ConstantBuffer<T>} resource class.
719+
720+
\p The template parameter \texttt{T} must be a class type (\ref{Classes}).
721+
722+
\begin{HLSL}
723+
template <typename T>
724+
class ConstantBuffer {
725+
public:
726+
ConstantBuffer();
727+
ConstantBuffer(const ConstantBuffer &buf);
728+
ConstantBuffer &operator=(ConstantBuffer &buf);
729+
};
730+
\end{HLSL}
731+
732+
\p The \textit{shader constants} are the fields of the class type \texttt{T}.
733+
They can be referenced from anywhere within the translation unit after the
734+
\texttt{ConstantBuffer<T>} declaration as if they were fields of the
735+
\texttt{ConstantBuffer<T>} class.
736+
737+
\p For example:
738+
739+
\begin{HLSL}
740+
struct MyConstants {
741+
float4 CameraPos;
742+
};
743+
744+
ConstantBuffer<MyConstants> CB;
745+
746+
float4 getCameraPosition() {
747+
return CB.CameraPos;
748+
}
749+
\end{HLSL}
750+
751+
\p The layout rules for constant buffer declared with the
752+
\texttt{ConstantBuffer<T>} syntax are the same as for named \texttt{cbuffer}
753+
declaration groups.
754+
755+
\p \texttt{ConstantBuffer<T>} can be defined at local scope to represent a local
756+
reference to a constant buffer that can be associated with a global buffer when
757+
assigned. The reference must be resolvable to a unique global buffer declaration
758+
before use.
759+
760+
\p Constant buffers cannot be implicitly nor explicitly cast from one type to
761+
another. This means that local \texttt{ConstantBuffer} can only be assigned from
762+
\texttt{ConstantBuffer} with the same template type \texttt{T}.
763+
764+
\Sub{Constant Buffer Layout}{Resources.cnbuf.lay}
765+
766+
\p Layout of the constant buffer is implementation dependent. This section
767+
describes the layout that is used by DirectX.
768+
769+
\p A constant buffer is arranged like an array of 16-byte rows, or 4-component
770+
vectors of 32-bit elements. Shader constants are arranged into the buffer in the
771+
order they were declared based on following rules.
772+
773+
\p Specific basic types are packed into the last used row of the buffer if they
774+
fit into the available space, starting at the next available aligned position.
775+
These types include:
776+
\begin{itemize}
777+
\item \textit{scalar types}
778+
\item \textit{vector types}
779+
\item \textit{matrix types} with only one row in \textit{column\_major} storage layout
780+
\end{itemize}
781+
782+
\p If they do not fit the remaining space of the row, they will placed at the
783+
start a new 16-byte aligned row.
784+
785+
\p Vectors are aligned by the size of a single vector element type unless that
786+
alignment results in crossing the 16-byte row boundary, in which case it is
787+
aligned to the next row.
788+
789+
\p Aggregate types like arrays and structures are always 16-byte row-aligned. If
790+
the aggregate ends with an element that does not completely fill a row, the
791+
remaining space on the last row may be used by the next value.
792+
793+
\p Individual array elements are always 16-byte row aligned.
794+
795+
\p Matrix types with more than one row in \textit{column\_major} storage layout
796+
and matrix types in \textit{row\_major} storage layout in are aligned to the
797+
16-byte row. Each row in storage layout (each column for \textit{column\_major}
798+
matrix) is aligned to a 16-byte row.
799+
800+
\p Members of structured types used in constant buffers follow these same rules.
801+
Because structures are always 16-byte row-aligned, the offset layout within the
802+
structure is independent of the particular structure instance location.
803+
804+
\Sub{Packoffset annotations}{Resources.cnbuf.po}
805+
806+
\p Shader constants declared in \texttt{cbuffer} declaration group can have an
807+
optional \texttt{packoffset} annotation added before their \texttt{;} terminal.
808+
If this annotation is added to one shader constant in a declaration group then
809+
it must be added to all shader constants in that group.
810+
811+
\begin{grammar}
812+
\define{packoffset-annotation}\br
813+
\terminal{: packoffset(} packoffset-id packoffset-row \opt{packoffset-element} \terminal{)}
814+
815+
\define{packoffset-id}\textnormal{one of}\br
816+
\terminal{c C}
817+
818+
\define{packoffset-row}\br
819+
digit\br
820+
packoffset-row digit
821+
822+
\define{packoffset-element}\br
823+
\terminal{.} \textit{packoffset-element-id}
824+
825+
\define{packoffset-element-id}\textnormal{one of}\br
826+
\terminal{x y z w r g b a}\br
827+
\end{grammar}
828+
829+
\p The \texttt{packoffset} annotation defines specific offset in the constant
830+
buffer where the shader constant is located.
831+
832+
\p The \textit{packoffset-row} number is the index into the array of 16-byte
833+
rows of the constant buffer. Each row treated as a vector of four 32-bit
834+
elements.
835+
836+
\p The \textit{packoffset-element} identifies specific location within the
837+
vector where \texttt{x} or \texttt{r} is the first element of the vector,
838+
\texttt{y} or \texttt{g} is the second one, \texttt{z} or \texttt{b} is the
839+
third one and \texttt{w} or \texttt{a} is the fourth, and last element of the
840+
vector.
841+
842+
\p Shader constant that has a structure, array or matrix type must always be
843+
16-byte row-aligned. It means that if it specifies a
844+
\textit{packoffset-element}, it must have a value of \texttt{x} or \texttt{r}.
845+
846+
\p For example
847+
848+
\begin{HLSL}
849+
cbuffer MyConstants {
850+
float2 Pos : packoffset(c1.z);
851+
};
852+
\end{HLSL}
853+
854+
The \texttt{Pos} shader constant will be located at byte offset \texttt{24} in
855+
the constant buffer \texttt{MyConstants}.
856+
857+
\Sub{Default Constant Buffer}{Resources.cnbuf.defcb}
858+
859+
\p All variables declarations in the global scope are implicitly added to
860+
default constant buffer called \texttt{\$Globals}, unless they are marked
861+
\texttt{static}, \texttt{groupshared}, or declare a resource or array of
862+
resources.
863+
864+
\p Layout rules for a default constant buffer are the same as for a named
865+
\texttt{cbuffer} declaration group.
866+
867+
\p Default constant buffer declarations can have an optional
868+
\textit{resource-binding} annotation with a \textit{register-type} \texttt{c} or
869+
\texttt{C} added before their \texttt{;} terminal. This annotation does not
870+
define a virtual register binding but rather an index into an array of 16-byte
871+
rows that represents the default constant buffer, similar to the
872+
\texttt{packoffset} annotation.
873+
874+
\p For example
875+
\begin{HLSL}
876+
float4 CameraPos : register(c2);
877+
\end{HLSL}
878+
879+
is equivalent to
880+
881+
\begin{HLSL}
882+
cbuffer CB {
883+
float4 CameraPos : packoffset(c2);
884+
}
885+
\end{HLSL}
886+
666887
\Sec{Samplers}{Resources.samp}
667888

668889
\Sec{CheckAccessFullyMapped}{Resources.mapcheck}
669890

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

672894
\begin{HLSL}
673895
bool CheckAccessFullyMapped(in uint status);
674896
\end{HLSL}
675897

676-
This function returns true is the value was accessed from a fully committed resource,
677-
or from fully mapped pages of a sparse resource.
678-
If any part of the return value was from unmapped memory, false is returned.
898+
This function returns true if the value was accessed from a fully committed
899+
resource, or from fully mapped pages of a sparse resource. If any part of the
900+
return value was from unmapped memory, false is returned.
679901

680902
\Sec{Resource Binding}{Resources.binding}
681903

@@ -688,16 +910,21 @@
688910
\terminal{: register(} register-type bind-number \terminal{)}\br
689911
\terminal{: register(} register-type bind-number , \terminal{space} bind-number \terminal{)}\br
690912
\define{register-type} \textnormal{one of}\br
691-
\terminal{t u b s}\br
913+
\terminal{t u b s c T U B S C}\br
692914
\define{bind-number}\br
693915
digit\br
694916
bind-number digit\br
695917
\end{grammar}
696918

697-
The register type indicates whether the binding is for a read-only (\texttt{t}), a writable (\texttt{u}),
698-
a constant buffer (\texttt{b}), or a sampler (\texttt{s}).
699-
The register bind number indicates the register number at which the resource variable begins.
700-
The optional second parameter indicates the virtual register space that the register belongs to.
919+
The register type indicates whether the binding is for a read-only
920+
(\texttt{t}/\texttt{T}), a writable (\texttt{u}/\texttt{U}), a constant buffer
921+
(\texttt{b}/\texttt{B}), or a sampler (\texttt{s}/\texttt{S}). The register bind
922+
number indicates the register number at which the resource variable begins. The
923+
optional second parameter indicates the virtual register space that the register
924+
belongs to.
925+
926+
Register type \texttt{c}/\texttt{C} defines layout information for the default
927+
constant buffer (\ref{Resources.cnbuf.defcb}).
701928

702929
Sample syntax of virtual register binding attributes:
703930
\begin{HLSL}

0 commit comments

Comments
 (0)