HLSL: allow "sample" in expressions.
Unlike other qualifiers, HLSL allows "sample" to be either a qualifier keyword or an identifier (e.g, a variable or function name). A fix to allow this was made a while ago, but that fix was insufficient when 'sample' was used in an expression. The problem was around the initial ambiguity between: sample float a; // "sample" is part of a fully specified type and sample.xyz; // sample is a keyword in a dot expression Both start the same. The "sample" was being accepted as a qualifier before enough further parsing was done to determine we were not a declaration after all. This consumed the token, causing it to fail for its real purpose. Now, when accepting a fully specified type, the token is pushed back onto the stack if the thing is not a fully specified type. This leaves it available for subsequent purposes. Changed the "hlsl.identifier.sample.frag" test to exercise this situation, distilled down from a production shaders.
This commit is contained in:
parent
abf5057948
commit
a64ed3eba0
@ -12,18 +12,27 @@ gl_FragCoord origin is upper left
|
|||||||
0:12 Function Parameters:
|
0:12 Function Parameters:
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:15 Sequence
|
0:15 Sequence
|
||||||
0:15 move second child to first child (temp int)
|
0:15 move second child to first child (temp 4-component vector of float)
|
||||||
0:15 'sample' (temp int)
|
0:15 'sample' (temp 4-component vector of float)
|
||||||
0:15 Constant:
|
0:? Constant:
|
||||||
0:15 3 (const int)
|
0:? 3.000000
|
||||||
|
0:? 4.000000
|
||||||
|
0:? 5.000000
|
||||||
|
0:? 6.000000
|
||||||
0:17 Sequence
|
0:17 Sequence
|
||||||
0:17 move second child to first child (temp 4-component vector of float)
|
0:17 move second child to first child (temp 4-component vector of float)
|
||||||
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
||||||
0:? Constant:
|
0:17 vector swizzle (temp 4-component vector of float)
|
||||||
0:? 0.000000
|
0:17 'sample' (temp 4-component vector of float)
|
||||||
0:? 0.000000
|
0:17 Sequence
|
||||||
0:? 0.000000
|
0:17 Constant:
|
||||||
0:? 0.000000
|
0:17 0 (const int)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 1 (const int)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 2 (const int)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 3 (const int)
|
||||||
0:17 Branch: Return
|
0:17 Branch: Return
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
||||||
@ -45,54 +54,67 @@ gl_FragCoord origin is upper left
|
|||||||
0:12 Function Parameters:
|
0:12 Function Parameters:
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:15 Sequence
|
0:15 Sequence
|
||||||
0:15 move second child to first child (temp int)
|
0:15 move second child to first child (temp 4-component vector of float)
|
||||||
0:15 'sample' (temp int)
|
0:15 'sample' (temp 4-component vector of float)
|
||||||
0:15 Constant:
|
0:? Constant:
|
||||||
0:15 3 (const int)
|
0:? 3.000000
|
||||||
|
0:? 4.000000
|
||||||
|
0:? 5.000000
|
||||||
|
0:? 6.000000
|
||||||
0:17 Sequence
|
0:17 Sequence
|
||||||
0:17 move second child to first child (temp 4-component vector of float)
|
0:17 move second child to first child (temp 4-component vector of float)
|
||||||
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
||||||
0:? Constant:
|
0:17 vector swizzle (temp 4-component vector of float)
|
||||||
0:? 0.000000
|
0:17 'sample' (temp 4-component vector of float)
|
||||||
0:? 0.000000
|
0:17 Sequence
|
||||||
0:? 0.000000
|
0:17 Constant:
|
||||||
0:? 0.000000
|
0:17 0 (const int)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 1 (const int)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 2 (const int)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 3 (const int)
|
||||||
0:17 Branch: Return
|
0:17 Branch: Return
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
||||||
|
|
||||||
// Module Version 10000
|
// Module Version 10000
|
||||||
// Generated by (magic number): 80001
|
// Generated by (magic number): 80001
|
||||||
// Id's are bound by 24
|
// Id's are bound by 28
|
||||||
|
|
||||||
Capability Shader
|
Capability Shader
|
||||||
1: ExtInstImport "GLSL.std.450"
|
1: ExtInstImport "GLSL.std.450"
|
||||||
MemoryModel Logical GLSL450
|
MemoryModel Logical GLSL450
|
||||||
EntryPoint Fragment 4 "main" 20
|
EntryPoint Fragment 4 "main" 25
|
||||||
ExecutionMode 4 OriginUpperLeft
|
ExecutionMode 4 OriginUpperLeft
|
||||||
Name 4 "main"
|
Name 4 "main"
|
||||||
Name 10 "sample(i1;"
|
Name 10 "sample(i1;"
|
||||||
Name 9 "x"
|
Name 9 "x"
|
||||||
Name 15 "sample"
|
Name 18 "sample"
|
||||||
Name 20 "@entryPointOutput"
|
Name 25 "@entryPointOutput"
|
||||||
Decorate 20(@entryPointOutput) Location 0
|
Decorate 25(@entryPointOutput) Location 0
|
||||||
2: TypeVoid
|
2: TypeVoid
|
||||||
3: TypeFunction 2
|
3: TypeFunction 2
|
||||||
6: TypeInt 32 1
|
6: TypeInt 32 1
|
||||||
7: TypePointer Function 6(int)
|
7: TypePointer Function 6(int)
|
||||||
8: TypeFunction 6(int) 7(ptr)
|
8: TypeFunction 6(int) 7(ptr)
|
||||||
16: 6(int) Constant 3
|
15: TypeFloat 32
|
||||||
17: TypeFloat 32
|
16: TypeVector 15(float) 4
|
||||||
18: TypeVector 17(float) 4
|
17: TypePointer Function 16(fvec4)
|
||||||
19: TypePointer Output 18(fvec4)
|
19: 15(float) Constant 1077936128
|
||||||
20(@entryPointOutput): 19(ptr) Variable Output
|
20: 15(float) Constant 1082130432
|
||||||
21: 17(float) Constant 0
|
21: 15(float) Constant 1084227584
|
||||||
22: 18(fvec4) ConstantComposite 21 21 21 21
|
22: 15(float) Constant 1086324736
|
||||||
|
23: 16(fvec4) ConstantComposite 19 20 21 22
|
||||||
|
24: TypePointer Output 16(fvec4)
|
||||||
|
25(@entryPointOutput): 24(ptr) Variable Output
|
||||||
4(main): 2 Function None 3
|
4(main): 2 Function None 3
|
||||||
5: Label
|
5: Label
|
||||||
15(sample): 7(ptr) Variable Function
|
18(sample): 17(ptr) Variable Function
|
||||||
Store 15(sample) 16
|
Store 18(sample) 23
|
||||||
Store 20(@entryPointOutput) 22
|
26: 16(fvec4) Load 18(sample)
|
||||||
|
Store 25(@entryPointOutput) 26
|
||||||
Return
|
Return
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
10(sample(i1;): 6(int) Function None 8
|
10(sample(i1;): 6(int) Function None 8
|
||||||
|
@ -12,7 +12,7 @@ float4 main() : SV_Target0
|
|||||||
{
|
{
|
||||||
// HLSL allows this as an identifier as well.
|
// HLSL allows this as an identifier as well.
|
||||||
// However, this is not true of other qualifier keywords such as "linear".
|
// However, this is not true of other qualifier keywords such as "linear".
|
||||||
int sample = 3;
|
float4 sample = float4(3,4,5,6);
|
||||||
|
|
||||||
return float4(0,0,0,0);
|
return sample.rgba; // 'sample' can participate in an expression.
|
||||||
}
|
}
|
||||||
|
@ -90,10 +90,11 @@ bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
|
|||||||
// as "linear" or "centroid" NOT valid identifiers. This code special cases "sample",
|
// as "linear" or "centroid" NOT valid identifiers. This code special cases "sample",
|
||||||
// so e.g, "int sample;" is accepted.
|
// so e.g, "int sample;" is accepted.
|
||||||
if (peekTokenClass(EHTokSample)) {
|
if (peekTokenClass(EHTokSample)) {
|
||||||
idToken.string = NewPoolTString("sample");
|
token.string = NewPoolTString("sample");
|
||||||
idToken.tokenClass = EHTokIdentifier;
|
token.tokenClass = EHTokIdentifier;
|
||||||
idToken.symbol = nullptr;
|
token.symbol = nullptr;
|
||||||
idToken.loc = token.loc;
|
|
||||||
|
idToken = token;
|
||||||
advanceToken();
|
advanceToken();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -475,8 +476,15 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type)
|
|||||||
TSourceLoc loc = token.loc;
|
TSourceLoc loc = token.loc;
|
||||||
|
|
||||||
// type_specifier
|
// type_specifier
|
||||||
if (! acceptType(type))
|
if (! acceptType(type)) {
|
||||||
|
// If this is not a type, we may have inadvertently gone down a wrong path
|
||||||
|
// py parsing "sample", which can be treated like either an identifier or a
|
||||||
|
// qualifier. Back it out, if we did.
|
||||||
|
if (qualifier.sample)
|
||||||
|
recedeToken();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (type.getBasicType() == EbtBlock) {
|
if (type.getBasicType() == EbtBlock) {
|
||||||
// the type was a block, which set some parts of the qualifier
|
// the type was a block, which set some parts of the qualifier
|
||||||
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
|
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
|
||||||
@ -2203,7 +2211,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
|
|||||||
} else if (acceptIdentifier(idToken)) {
|
} else if (acceptIdentifier(idToken)) {
|
||||||
// identifier or function_call name
|
// identifier or function_call name
|
||||||
if (! peekTokenClass(EHTokLeftParen)) {
|
if (! peekTokenClass(EHTokLeftParen)) {
|
||||||
node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
|
node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
|
||||||
} else if (acceptFunctionCall(idToken, node)) {
|
} else if (acceptFunctionCall(idToken, node)) {
|
||||||
// function_call (nothing else to do yet)
|
// function_call (nothing else to do yet)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user