-
Notifications
You must be signed in to change notification settings - Fork 853
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
Support specialization composite constants #211
Support specialization composite constants #211
Conversation
@dekimir @dneto0 @johnkslang @AWoloszyn PTAL. One thing I'm not sure is whether the tests cover enough cases. |
@@ -484,7 +484,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn | |||
TIntermTyped* result = nullptr; | |||
|
|||
int indexValue = 0; | |||
if (index->getQualifier().isConstant()) { | |||
if (index->getQualifier().isFrontEndConstant()) { |
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.
calling isFrontEndConstant() means specialization constants won't get into the branch.
I think we do not need to check the index value for spec constants here, as we actually don't know their value, and checking based on their default values may not be very useful?
If we do need to check for the default value, that probably will be in another PR?
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.
their default values may not be very useful
Default values should be useful.
That being said, I agree we can apply this change and postpone a bit.
Another point to consider (for a future PR):
- merging together the subtree and the "constant union array" to one object, so that generally higher-level code like this doesn't care about that detail (this could also save memory, as they are mutually exclusive, and should be a union somewhere)
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.
Probably will have a future PR for it :)
Added a few comments. Other than that, it's looking good, on the right track.
First goal is to support what existing CTS tests already want to do with GLSL. Second goal is providing 100% functionality. I suspect the latter will require fine-tuning KHR_vulkan_glsl a bit. |
3b3bdb1
to
1259a23
Compare
Hi @Qining, not sure if you had a chance to test this with spec constant tests in CTS (there's an open MR for them), but this fails on the following syntax:
The culprit bit is the cast to float, which triggers an assertion Also nested initializer list syntax doesn't work with specialization constants:
This triggers an assertion here: A great deal of tests passes with this change, so thank you for your work! |
Hi @yavn, thanks for your test cases. I just checked these cases.
Actually the goal of this PR is to enable the spec constants tests in CTS. I will go ahead to test them. |
Hi @yavn, Please checkout the latest commit, the two failures should have been fixed by now. I will go and take a look in the CTS tests. |
} else | ||
return nullptr; | ||
} | ||
|
||
TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc); | ||
if (constructor->getType().getQualifier().isConstant() && specConst) | ||
if (isConstConstrutor && hasSpecConst) |
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.
Hi @johnkslang , I think the constness of a constructor should depends on its components, or sequence if it is a aggregate type. And the variable (or say symbol?) declared with the constructor has its own type to determine if the AST node should be const or not, but its constructor (or say initializer)'s type should not be determined by the variable.
Please correct me if I'm wrong.
Determining the constructor's constness from its own sequence solved the following problem.
const user_define_struct s = {const_a, {spec_const_1, const_b}, const_c};
When we build up the inner struct, we don't have a variable whose storage is EvqConst, so the original code will not label the inner struct as SpecConst, but an temporary aggregate. This caused the second assertion failure mentioned in Yavn's post.
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.
Yes, somewhere I discussed the issue of this being partly top down and partly bottom up.
Agreed that the spec.-constness aspect of a composite needs to be built bottom up. Unfortunately, other aspects of type in
const <type> <var> = <initializer>;
Come from <type>
, not from the deduced type of <initializer>
. It would be great to make it all bottom up, but perhaps off topic.
I assume it will suffice to get the correct bottom-up preservation of spec-constness in place, yes?
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.
Yes, your last email help me a lot in understanding the code and find out where the issue is.
And I think it is sufficient, but I haven't tested with CTS tests.
Everything related to composite constants passes now. There is some syntax that still fails, but I don't think it's the topic of this pull request:
Another issue is work group size specialization. It works, but I can't tell if it emits correct SPIR-V. I think it does, but my implementation doesn't handle it correctly. This might be a gray area in the spec. |
Hi @yavn, I confirmed the result. It is the same on my machine. I will file an issue in Vulkan repo about the a0[2 + sc0] = problem. The spec doesn't say how to behave in such a case. The working group size specialization is not handled (and should be affected) by this CL. I can take a look of it later, probably should treat it the same as other aggregate variable? |
Hi @yavn, another failure this CL will have with the CTS tests is the |
Note the specification says
So, along those lines, this should not work:
But, perhaps the spec. can more explicitly list this kind of initializer (since it's not really an assignment, and it's the initializee that was specialized). |
Oh, I didn't notice that... I'll update the tests to address this. |
I've filed an issue in the Khronos gitlab vulkan/vulkan repo. Probably we should list more explicitly in the Spec about this case. |
The point is that "per array element" code should not get generated (or input from GLSL), and have to change size, when a specialization constant changes value. It should be a fixed (constant) amount of "fix up" to change the size of a specialization constant. The list should be whatever that is. |
b07baac
to
2c4c5ec
Compare
Fix issue KhronosGroup#163, support creation and reference of composite type specialization constants. e.g.: ``` layout(constant_id = 200) const float myfloat = 1.25; layout(constant_id = 201) const int myint = 14; struct structtype { float f; int i; }; const structtype outer_struct_var = {myfloat, myint}; void main(){} ``` generated code (use glslangValidator): ``` // Module Version 10000 // Generated by (magic number): 80001 // Id's are bound by 12 Capability Shader 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Vertex 4 "main" Source GLSL 450 Name 4 "main" Name 10 "structtype" MemberName 10(structtype) 0 "f" MemberName 10(structtype) 1 "i" Decorate 7 SpecId 200 Decorate 9 SpecId 201 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 7: 6(float) SpecConstant 1067450368 8: TypeInt 32 1 9: 8(int) SpecConstant 14 10(structtype): TypeStruct 6(float) 8(int) 11:10(structtype) SpecConstantComposite 7 9 4(main): 2 Function None 3 5: Label Return FunctionEnd ``` Rname two function names to match their functionalities. 1) Rename `GlslangToSpvTraverser::createSpvSpecConstant()` to `createSpvConstant()`; 2) Rename `GlslangToSpvTraverser::createSpvConstant()` to `createSpvConstantFromConstUnionArray()` Add function `GlslangToSpvTraverser::createSpvConstantFromSubTree()` to handle constant creation from sub trees (e.g.: specialization constants). Related PR: KhronosGroup#208
2c4c5ec
to
0840838
Compare
@@ -3851,6 +3854,66 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT | |||
return builder.makeCompositeConstant(typeId, spvConsts); | |||
} | |||
|
|||
// Create constant ID from const initializer sub tree. | |||
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( | |||
const glslang::TIntermTyped* subTree) { |
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.
Have function open '{' start a new line.
Fix issue #163, support creation and usage of composite type
specialization constants.
e.g.:
generated code (use glslangValidator):
Rname two function names to match their functionalities.
GlslangToSpvTraverser::createSpvSpecConstant()
tocreateSpvConstant()
;GlslangToSpvTraverser::createSpvConstant()
tocreateSpvConstantFromConstUnionArray()
Add function
GlslangToSpvTraverser::createSpvConstantFromSubTree()
tohandle constant creation from sub trees (e.g.: specialization constants).
Related PR: #208