-
Notifications
You must be signed in to change notification settings - Fork 50
[0002] Detail attributes that will replace HLSL annotations #534
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
base: main
Are you sure you want to change the base?
[0002] Detail attributes that will replace HLSL annotations #534
Conversation
This adds language about removing HLSL annotation syntax as well as some proposed specification language. It also details the specific transformations of HLSL annotation attributes to general attributes.
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.
Overall I'm happy with this, unifying a bit how we write attributes across vk/hlsl.
I think we'd need to explicit a bit more the behavior changes between the APIs like how semantic indexing changes (same way you explicitly sais how register/index means binding/descriptor in the VK workd).
But overall, in the right direction!
general behavior described here. | ||
|
||
An empty attribute specifier has no effect. The order in which attributes | ||
applied to the same source construct are written shall not be significant. When |
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.
So this means attribute overriding/duplication/conflict will be determined by each attribute definition?
Like if I did uint field [[hlsl::system_value(something), hlsl::system_value(something_else)]]
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.
Yea, and conflicting attributes should generally be an error.
proposals/0002-cxx-attributes.md
Outdated
In Vulkan, the first value maps as the descriptor index, and the second maps as | ||
the descriptor set index. | ||
|
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.
Shall descriptor index
be replaced with binding index
? Since in SPIR-V those are Binding
and DescriptorSet
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'm fine with the general direction. I'd like to see some of the details for the attributes where DX and VK are different fleshed out a little more.
|
||
The following new attributes are introduced to replace HLSL annotations. | ||
|
||
#### hlsl::user_value(string[, int=0]) |
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.
In SPIR-V, we currently ignore the user semantics. We assign a location based on the order in which variables are declared, or using the vk::location
attribute. There have also been requests to allow the users to specify the component for the input as well as the location.
This does does not really work for SPIR-V since we have no good way to turn the string into a location index. The only thing we do with the the user semantic is to keep it around for reflection information.
I don't know if we want to try to come up with something like hlsl::binding
that would be well defined for both DX and SPIR-V. Then we could deprecate vk::location
, and close issues for the component.
Maybe something like hlsl::user_value(string[, int=0, int=0])
, with the statement: "The interpretation of this attribute is
defined by the target runtime's binding model." Then we can define DX and Vulkan behaviour separately.
@Keenuts any more thoughts?
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've read this more as a 'rewrite' of the attribute form with a new syntax, but also assumed we'd need to ignore this in SPIR-V since Location index is independant from the user semantic.
I think we could keep the split we have today and either use the parameter index ignoring the content, or ass vk-specific attributes for component/location.
void main([[hlsl_user_value("MYSEMANTIC"), vk::location(0), vk::component(1)]] float a)
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 had been thinking of this as just replacing the semantic as captured in reflection for SPIRV. That's more or less all it really is for DX too although it is expressed into the signatures rather than shader reflection.
I'd like to think more about how to handle location and component packing.
argument to the attribute is a string which can contain any valid C-string. The | ||
second optional value is an index. | ||
|
||
#### hlsl::system_value(enum[, int=0]) |
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.
@Keenuts Which system values have an index, and how do we handle those for SPIR-V in DXC?
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.
It depends on the system value:
Compute related ones have no index, same for semantic like POINT_SIZE. Those are builtins. But for SV_TARGET
, which has an index, we emit a Location
decoration.
`c<row>.<column_letter>` map to the new attribute as `hlsl::packoffset(<row>, | ||
<column_index>)`, where `<column_index>` maps as in the table below. | ||
|
||
| column_letter | column_index | |
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.
considering payload_access
allows identifiers, I'm curious why we are changing to integers here? The previous use of letters is fairly arbitrary and not any easier/harder to understand than integers, but the reverse holds, and this would be asking our users to get used to a new way of writing something
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.
My reasoning for getting rid of the prefix character c
is that it can only ever be c
which has meaning in DirectX (it's a CBV resource), but has no meaning in other binding models.
In terms of the column index. I can see an argument for it remaining a letter. I struggle a bit with it because it is effectively a sub-index to 32-bit offsets, which actually isn't valid for all types. For example you can't use an offset of y
today for a 64-bit data member so your offsets available are only x
and z
, which just feels weird. Not that offsets 0
and 2
is really entirely better.
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 guess the other advantage that integers would have is that they can be integer constant expressions not just static values. So using integers would enable someone to do something like:
template <typename T, int X>
constexpr int toOffset() {
constexpr int Val = (sizeof(T) / 4) * X;
static_assert(Val <= 3);
return Val
}
...
double V [[hlsl::packoffset(0, toOffset<double,2>())]];
We could also consider supporting either integers or identifiers.
I'd be curious for @tex3d's thoughts here too.
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.
My reasoning for getting rid of the prefix character
c
Yeah I wasn't concerned about dropping the c
. More so that we'd be moving somewhat arbitrarily from hlsl::binding(0,y)
to hlsl::binding(0,2)
.
I think it's not really an issue since we are also rewriting the rest of the attribute but its at least worth considering given the tools and guides written around the notion that the second value is a letter.
I personally thing integer is simpler/clearer and think from a clean slate that it's the right decision, I just want to make sure we aren't negatively impacting users
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.
@V-FEXrt - I think you meant moving from packoffset(c0,y)
to hlsl::packoffset(0,2)
, right? hlsl::binding
is described bellow.
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 sorry, that's what I meant. I don't think it's an issue worth blocking over. Just something to consider
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.
Look good, just a few comments and suggestions.
uint i [[hlsl::system_value(RenderTargetArrayIndex)]]; // applies to `i`. | ||
[[hlsl::system_value(RenderTargetArrayIndex)]] uint j; // applies to `j`. | ||
uint &[[hlsl::AddressSpace(1)]] Ref = ...; // applies to the type `uint &`. |
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.
uint i [[hlsl::system_value(RenderTargetArrayIndex)]]; // applies to `i`. | |
[[hlsl::system_value(RenderTargetArrayIndex)]] uint j; // applies to `j`. | |
uint &[[hlsl::AddressSpace(1)]] Ref = ...; // applies to the type `uint &`. | |
uint i [[hlsl::system_value(RenderTargetArrayIndex)]]; // applies to `i`. | |
[[hlsl::system_value(RenderTargetArrayIndex)]] uint j; // applies to `j`. | |
uint &[[hlsl::address_space(1)]] Ref = ...; // applies to the type `uint &`. |
The attribute names should have consistent naming pattern.
``` | ||
|
||
 | ||
|
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.
Each attribute may specify specific behavior for parsing attribute arguments. | ||
Any attribute that does not specify specific parsing behavior shall be parsed | ||
with the general behavior described here. | ||
|
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.
Each attribute may specify specific behavior for parsing attribute arguments. | |
Any attribute that does not specify specific parsing behavior shall be parsed | |
with the general behavior described here. | |
Each attribute may define specific behavior for how its arguments are parsed. | |
Attributes that do not define custom parsing behavior shall be parsed according to the general rules outlined here. |
attribute (e.g. keywords). Name lookup is not performed on identifiers within | ||
attribute-tokens. The attribute-token refers to the attribute being parsed, | ||
which determines requirements for parsing the optional | ||
attribute-argument-clause. |
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.
attribute (e.g. keywords). Name lookup is not performed on identifiers within | |
attribute-tokens. The attribute-token refers to the attribute being parsed, | |
which determines requirements for parsing the optional | |
attribute-argument-clause. | |
attribute (e.g. keywords). Name lookup is not performed on identifiers within | |
_attribute-token_. The _attribute-token_ refers to the attribute being parsed, | |
which determines requirements for parsing the optional | |
_attribute-argument-clause_. |
Consider making grammar tokens references in italic.
For attribute-tokens not specified in this specification the behavior is | ||
implementation-defined. |
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.
For attribute-tokens not specified in this specification the behavior is | |
implementation-defined. | |
The behavior of _attribute-token_ not specified in this specification is | |
implementation-defined. |
implementation-defined. | ||
|
||
Two consecutive square bracket tokens shall only appear when introducing an | ||
attribute-specifier. Any other occurrence of two consecutive square brackets is |
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.
attribute-specifier. Any other occurrence of two consecutive square brackets is | |
_attribute-specifier_. Any other occurrence of two consecutive square brackets is |
|
||
Two consecutive square bracket tokens shall only appear when introducing an | ||
attribute-specifier. Any other occurrence of two consecutive square brackets is | ||
ill-formed. |
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.
Doesn't
"Any other occurrence of two consecutive square brackets is ill-formed."
conflict with
"An empty attribute specifier has no effect. "?
|
||
With the introduction of C++ attribute syntax the HLSL annotation syntax will be | ||
removed from the language. In Clang, C++ attribute syntax can be supported in | ||
both HLSL 202x and 202y language modes with deprecation warnings, fix-it and |
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.
both HLSL 202x and 202y language modes with deprecation warnings, fix-it and | |
both HLSL 202x and 202y language modes with deprecation warnings reported for the old HLSL annotation syntax, including fix-it and |
`c<row>.<column_letter>` map to the new attribute as `hlsl::packoffset(<row>, | ||
<column_index>)`, where `<column_index>` maps as in the table below. | ||
|
||
| column_letter | column_index | |
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.
@V-FEXrt - I think you meant moving from packoffset(c0,y)
to hlsl::packoffset(0,2)
, right? hlsl::binding
is described bellow.
struct [[raypayload]] Payload { | ||
float f [[payload_access(read, caller, anyhit), payload_access(write, caller, anyhit)]]; | ||
}; | ||
``` |
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 think it would be good to add similar rewriting examples for all the other attributes above.
This adds language about removing HLSL annotation syntax as well as some proposed specification language. It also details the specific transformations of HLSL annotation attributes to general attributes.
Fixes #527