-
Notifications
You must be signed in to change notification settings - Fork 795
Allows Vulkan spec constants as attribute arguments. #7439
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?
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
9db3b6c
to
243acbc
Compare
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 mind this change generally. It will be good for SPIR-V.
I don't know if this is complete yet (it is still a draft). I pointed out one issue with using LocalSize
. You might also need to look at SpirvEmitter::addDerivativeGroupExecutionMode()
. That function determines which derivative group execution mode to add based on the number of threas in the group. However, if you have a spec constant for the number of threads, we cannot do that.
58352af
to
357813d
Compare
357813d
to
8e898bf
Compare
Why was Of course, since there's no access to specializations at compile time, there's no way to ensure the best choice of execution mode with spec constants anyway. However, in some cases partial information would be sufficient to rule out one of them. If both are possible, maybe pick one and issue a warning? |
It was implemented that way because that was the HLSL spec implemented for DXIL. See Thread Groups and Quads. I don't mind if we diverge from it when there are specialization constants. We just need to document it.
That is a reasonable idea. Longer term, we could try to add explicit attribute that apply to the entry point that would override the guess. |
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, but requires some tests.
Also restores file inadvertently committed source file changed for debugging.
tools/clang/test/CodeGenSPIRV/vk.spec-constant.attributes.derivative-group.hlsl
Show resolved
Hide resolved
tools/clang/test/CodeGenSPIRV/vk.spec-constant.attributes.derivative-group.hlsl
Show resolved
Hide resolved
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 there is a lot of missing test coverage here. You're making a bunch of attributes that had previously either required integer literal arguments or optional integer literal arguments now support constant expressions and specialization constants.
We really need test coverage for each attribute's change in behavior, and the error states. In particular it doesn't seem to me like you're actually handling the possible error of a non-constant expression being provided as a value. I think it just silently replaces the value with the default (which would be bad).
tools/clang/lib/CodeGen/CGHLSLMS.cpp
Outdated
@@ -328,6 +328,19 @@ class CGMSHLSLRuntime : public CGHLSLRuntime { | |||
}; | |||
} // namespace | |||
|
|||
static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | |||
uint32_t defaultVal = 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.
uint32_t defaultVal = 0) { | |
uint32_t defaultVal) { |
Doesn't look like this is ever called without a default value.
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 changed this to use llvm::Optional so that an absent default indicates that expr should be non-null. (See note on SemaHLSL below.)
const uint NumThreadsY = 1; | ||
#endif | ||
|
||
[numthreads(NumThreadsX,NumThreadsY,1)] |
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 other test cases that are probably interesting:
uint CBufferValue;
[numthreads(CbufferValue, 1, 1)] // Should error
void main() {}
const uint Eight = 8;
[numthreads(Eight * 2, Eight, 1)] // Should work
void main() {}
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 latter won't work but would if declared static. Larger expressions incorporating spec constants don't work in the current version.
I've added preprocessor directives to vk.spec-constants.attributes.hlsl to enable removal of the spec constant designations to test for expected errors.
tools/clang/lib/Sema/SemaHLSL.cpp
Outdated
static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | ||
uint32_t defaultVal = 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.
static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | |
uint32_t defaultVal = 0) { | |
static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | |
uint32_t defaultVal) { |
It is really unfortunate to completely duplicate this code, and I don't think the two should be identical. In this version in Sema we should be surfacing an error if there is an expression that isn't a constant expression or spec constant.
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.
Sema already seems to complain in all the relevant cases, though I have added some more diagnostics. Of the arguments allowed to be spec constants, the only optional one is the NodeId index, so maybe just return zero (possibly after issuing an error) whenever expr is null? For now the function works as described for the CGHLSLMS version.
return (uint32_t)apsInt.getSExtValue(); | ||
if (expr->isVulkanSpecConstantExpr(astContext, &apValue) && apValue.isInt()) | ||
return (uint32_t)apValue.getInt().getSExtValue(); | ||
} |
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.
} | |
llvm_unreachable("Expression must be a constant expression or spec constant") | |
} |
We should be erroring in Sema if this isn't a constant expression or spec constant.
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.
Changed as suggested.
tools/clang/lib/CodeGen/CGHLSLMS.cpp
Outdated
@@ -328,6 +328,19 @@ class CGMSHLSLRuntime : public CGHLSLRuntime { | |||
}; | |||
} // namespace | |||
|
|||
static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, |
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.
You've got a fair amount of mixing coding style, and DXC is a bit inconsistent.
In general if you're adding code in a part of the codebase that isn't otherwise following a consistent style we follow the LLVM Coding Standards. LLVM uses CamelCase
for variable names and type names (see: https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly).
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.
Fixes #3092