-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add resource chapter documenting buffers and bindings #344
base: main
Are you sure you want to change the base?
Conversation
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 llvm/wg-hlsl#55 Fixes llvm/wg-hlsl#56
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial thoughts.
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/expressions.tex
Outdated
\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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resource types have overloads for operator[]
even in DXC. The original language did miss vector and matrix types, but the addition of resources is redundant.
specs/language/resources.tex
Outdated
// element access | ||
T operator[](uint pos); | ||
T Load(in int pos); | ||
T Load(in int pos, out uint status); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some (maybe all) of these methods should probably be const
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
\begin{HLSL} | ||
template <typename T = float4> | ||
class Buffer { | ||
Buffer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need a copy constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the copy constructors take references?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was hesitant to suggest references since we don't make them visible to the users, but I suppose that's the way the are in C++ and that's the metaphor we're using here even in cases where it doesn't reflect the actual implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use references elsewhere and when we do add references to the language I think it'll mean that this documentation just becomes correct.
I think that the copy constructors should take const references though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Responded to Damyan's comments
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Respond to @llvm-beanz comments. The extend of the changes merging many of the buffer descriptions made me unable to respond to some of the comments directly. I used the class inheritance metaphor to represent the relation between some buffer types.
\begin{HLSL} | ||
template <typename T = float4> | ||
class Buffer { | ||
Buffer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
specs/language/resources.tex
Outdated
// element access | ||
T operator[](uint pos); | ||
T Load(in int pos); | ||
T Load(in int pos, out uint status); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't fully read this yet, but I had a look through the changes that were directly in response to my previous feedback (thanks!)
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
Outdated
T operator[](int pos) const; | ||
T Load(in int pos) const; | ||
T Load(in int pos, out uint status) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I was suggesting that we should change the spec here, only call out that this somewhat surprising definition is actually what is intended and isn't a mistake.
Somehow I was unable to respond to this comment from @damyanp about similar lines of text directly. Probably a consequence of the consolidation I did.
I suspect perhaps the intent was to say "I wasn't suggesting that we should change the spec here"? That seems more consistent with the rest of the sentence. I could be persuaded either way, but I've brought all subscript ops and loads into line with a signed integer parameter for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, yes, your interpretation is correct.
@bogner - do the parameter types in this spec match what you've/'re implementing?
\begin{HLSL} | ||
template <typename T = float4> | ||
class Buffer { | ||
Buffer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the copy constructors take references?
specs/language/resources.tex
Outdated
T operator[](int pos) const; | ||
T Load(in int pos) const; | ||
T Load(in int pos, out uint status) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, yes, your interpretation is correct.
@bogner - do the parameter types in this spec match what you've/'re implementing?
specs/language/resources.tex
Outdated
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
must be resolvable to a unique global buffer
Just checking this is the case. So I couldn't do something like:
ByteAddressBuffer myBuf = globalBuffersArray[threadId];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resource arrays are different. If you can unambiguously map to the same resource array, that's fine. It's if you cross over into a separate resource entirely that you have problems:
https://godbolt.org/z/9Whzssxr1
ByteAddressBuffer globalBuffersArray[10];
ByteAddressBuffer globalBuffer;
RWBuffer<float4> outbuf;
[numthreads(8,1,1)]
void main(uint threadId: SV_GroupThreadID) {
ByteAddressBuffer myBuf;
myBuf = globalBuffersArray[threadId]; // This is fine
if (threadId > 10)
myBuf = globalBuffer; // This is not
outbuf[threadId] = myBuf.Load<float4>(0);
}
I'll try to come up with some wording that makes this clear and maybe add a note for the specific case
specs/language/resources.tex
Outdated
RWBuffer<float> 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resource aggregates structs containing multiple resources types or arrays of resource types or structs containing one or more resource types.
I might be tired, but I'm having a hard time parsing this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored it into a self-referential list of what constitutes an aggregate resource type. I think it's much clearer now.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Damyan! Responses in relation to the latest commit.
\begin{HLSL} | ||
template <typename T = float4> | ||
class Buffer { | ||
Buffer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was hesitant to suggest references since we don't make them visible to the users, but I suppose that's the way the are in C++ and that's the metaphor we're using here even in cases where it doesn't reflect the actual implementation.
specs/language/resources.tex
Outdated
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resource arrays are different. If you can unambiguously map to the same resource array, that's fine. It's if you cross over into a separate resource entirely that you have problems:
https://godbolt.org/z/9Whzssxr1
ByteAddressBuffer globalBuffersArray[10];
ByteAddressBuffer globalBuffer;
RWBuffer<float4> outbuf;
[numthreads(8,1,1)]
void main(uint threadId: SV_GroupThreadID) {
ByteAddressBuffer myBuf;
myBuf = globalBuffersArray[threadId]; // This is fine
if (threadId > 10)
myBuf = globalBuffer; // This is not
outbuf[threadId] = myBuf.Load<float4>(0);
}
I'll try to come up with some wording that makes this clear and maybe add a note for the specific case
specs/language/resources.tex
Outdated
RWBuffer<float> 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored it into a self-referential list of what constitutes an aggregate resource type. I think it's much clearer now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - a few nits in the comments, but I think this is pretty much ready to go in.
specs/language/resources.tex
Outdated
RWBuffer<float> herbuf : register(u0, space1); | ||
\end{HLSL} | ||
|
||
A aggregate resource type can be: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A aggregate resource type can be: | |
An aggregate resource type can be: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
specs/language/resources.tex
Outdated
\end{itemize} | ||
|
||
When aggregate resource types have register annotations, | ||
they occupy the first register they specify as well as however many additional sequential registers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they occupy the first register they specify as well as however many additional sequential registers | |
they occupy the first register they specify, as well as however many additional sequential registers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think a comma is required here. "as well as" serves the same function as "and". In retrospect, I'll change it to "and" for simplicity. I think that makes it clearer that the comma isn't needed since it's just a single conjunction.
specs/language/resources.tex
Outdated
|
||
\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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This includes elements of arrays of resources as such array elements must be indexed with literals. | |
This includes elements of arrays of resources, as such array elements must be indexed with literals. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't think this comma is needed. "As" serves the same purpose as "since", which I will replace it with for similar reasons as above.
This says that if it is a subordinate clause following the main close, no comma is needed. It is needed when it is a subordinate clause that precedes the main clause e.g. "Since such array elements must be indexed with literals, this includes elements of arrays of resources."
\begin{HLSL} | ||
template <typename T = float4> | ||
class Buffer { | ||
Buffer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use references elsewhere and when we do add references to the language I think it'll mean that this documentation just becomes correct.
I think that the copy constructors should take const references though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked with grammarly and copilot to verify my thinking about commas.
\begin{HLSL} | ||
template <typename T = float4> | ||
class Buffer { | ||
Buffer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
specs/language/resources.tex
Outdated
\end{itemize} | ||
|
||
When aggregate resource types have register annotations, | ||
they occupy the first register they specify as well as however many additional sequential registers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think a comma is required here. "as well as" serves the same function as "and". In retrospect, I'll change it to "and" for simplicity. I think that makes it clearer that the comma isn't needed since it's just a single conjunction.
specs/language/resources.tex
Outdated
|
||
\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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't think this comma is needed. "As" serves the same purpose as "since", which I will replace it with for similar reasons as above.
This says that if it is a subordinate clause following the main close, no comma is needed. It is needed when it is a subordinate clause that precedes the main clause e.g. "Since such array elements must be indexed with literals, this includes elements of arrays of resources."
specs/language/resources.tex
Outdated
RWBuffer<float> herbuf : register(u0, space1); | ||
\end{HLSL} | ||
|
||
A aggregate resource type can be: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
RWBuffer operator=(RWBuffer buf); | ||
|
||
// element access | ||
T &operator[](int n); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be T &operator[](size_t n);
?
Along the same lines, should the type of index
argument of Buffer::Load(...)
methods above be size_t
instead of int
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
T &operator[](size_t n);
?Along the same lines, should the type of
index
argument ofBuffer::Load(...)
methods above besize_t
instead ofint
?
Never mind. It would contradict the public API
public: | ||
Buffer(); | ||
Buffer(const Buffer &buf); | ||
Buffer operator=(Buffer buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Buffer operator=(Buffer buf); | |
Buffer &operator=(const Buffer &buf); |
public: | ||
RWBuffer(); | ||
RWBuffer(RWBuffer buf); | ||
RWBuffer operator=(RWBuffer buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RWBuffer operator=(RWBuffer buf); | |
RWBuffer &operator=(const RWBuffer &buf); |
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this wording slightly confusing. What is a "unique individual buffer" vs a "unique global declaration"?
I believe this and the next sentence have to do with arrays of resources, but that isn't clear to me from the wording here.
RWBuffer<int> lrwbuf = grwbuf; | ||
} | ||
\end{HLSL} | ||
Buffer operands to the assignment operator must have the same element type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps more simply:
Buffer types cannot be casted implicitly or explicitly.
The overload resolution of assignment operators isn't impacted.
public: | ||
ByteAddressBuffer(); | ||
ByteAddressBuffer(const ByteAddressBuffer &buf); | ||
ByteAddressBuffer operator=(ByteAddressBuffer buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ByteAddressBuffer operator=(ByteAddressBuffer buf); | |
ByteAddressBuffer &operator=(ByteAddressBuffer &buf); |
public: | ||
RWByteAddressBuffer(); | ||
RWByteAddressBuffer(const RWByteAddressBuffer &buf); | ||
RWByteAddressBuffer operator=(RWByteAddressBuffer buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RWByteAddressBuffer operator=(RWByteAddressBuffer buf); | |
RWByteAddressBuffer &operator=(RWByteAddressBuffer &buf); |
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}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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}. | |
The alignment requirements of \texttt{offset} for this operation is the alignment requirement of an object of type \texttt{T} in the device memory space (\ref{Intro.Memory.Spaces.Device}). |
I don't think we should be defining how the alignment requirement of a type is calculated here, instead we should define that elsewhere in the spec. You could add a placeholder reference for something like Intro.Memory.Alignment
as well to make sure we have a citation.
The buffer contents is treated as raw data and the casting to the given types | ||
is done bit for bit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take or leave this one, its very nitty.
The buffer contents is treated as raw data and the casting to the given types | |
is done bit for bit. | |
The buffer contents is treated as raw data. When accessed the bytes are interpreted as the target type with no conversions or interpolations applied. |
uint DecrementCounter(); | ||
\end{HLSL} | ||
|
||
Increment or decrements the hidden counter associated with the RWStructuredBuffer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the return value?
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 llvm/wg-hlsl#55
Fixes llvm/wg-hlsl#56