зеркало из https://github.com/stride3d/xkslang.git
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:
Родитель
abf5057948
Коммит
a64ed3eba0
|
@ -12,18 +12,27 @@ gl_FragCoord origin is upper left
|
|||
0:12 Function Parameters:
|
||||
0:? Sequence
|
||||
0:15 Sequence
|
||||
0:15 move second child to first child (temp int)
|
||||
0:15 'sample' (temp int)
|
||||
0:15 Constant:
|
||||
0:15 3 (const int)
|
||||
0:15 move second child to first child (temp 4-component vector of float)
|
||||
0:15 'sample' (temp 4-component vector of float)
|
||||
0:? Constant:
|
||||
0:? 3.000000
|
||||
0:? 4.000000
|
||||
0:? 5.000000
|
||||
0:? 6.000000
|
||||
0:17 Sequence
|
||||
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:? Constant:
|
||||
0:? 0.000000
|
||||
0:? 0.000000
|
||||
0:? 0.000000
|
||||
0:? 0.000000
|
||||
0:17 vector swizzle (temp 4-component vector of float)
|
||||
0:17 'sample' (temp 4-component vector of float)
|
||||
0:17 Sequence
|
||||
0:17 Constant:
|
||||
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:? Linker Objects
|
||||
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:? Sequence
|
||||
0:15 Sequence
|
||||
0:15 move second child to first child (temp int)
|
||||
0:15 'sample' (temp int)
|
||||
0:15 Constant:
|
||||
0:15 3 (const int)
|
||||
0:15 move second child to first child (temp 4-component vector of float)
|
||||
0:15 'sample' (temp 4-component vector of float)
|
||||
0:? Constant:
|
||||
0:? 3.000000
|
||||
0:? 4.000000
|
||||
0:? 5.000000
|
||||
0:? 6.000000
|
||||
0:17 Sequence
|
||||
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:? Constant:
|
||||
0:? 0.000000
|
||||
0:? 0.000000
|
||||
0:? 0.000000
|
||||
0:? 0.000000
|
||||
0:17 vector swizzle (temp 4-component vector of float)
|
||||
0:17 'sample' (temp 4-component vector of float)
|
||||
0:17 Sequence
|
||||
0:17 Constant:
|
||||
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:? Linker Objects
|
||||
0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 24
|
||||
// Id's are bound by 28
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Fragment 4 "main" 20
|
||||
EntryPoint Fragment 4 "main" 25
|
||||
ExecutionMode 4 OriginUpperLeft
|
||||
Name 4 "main"
|
||||
Name 10 "sample(i1;"
|
||||
Name 9 "x"
|
||||
Name 15 "sample"
|
||||
Name 20 "@entryPointOutput"
|
||||
Decorate 20(@entryPointOutput) Location 0
|
||||
Name 18 "sample"
|
||||
Name 25 "@entryPointOutput"
|
||||
Decorate 25(@entryPointOutput) Location 0
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeInt 32 1
|
||||
7: TypePointer Function 6(int)
|
||||
8: TypeFunction 6(int) 7(ptr)
|
||||
16: 6(int) Constant 3
|
||||
17: TypeFloat 32
|
||||
18: TypeVector 17(float) 4
|
||||
19: TypePointer Output 18(fvec4)
|
||||
20(@entryPointOutput): 19(ptr) Variable Output
|
||||
21: 17(float) Constant 0
|
||||
22: 18(fvec4) ConstantComposite 21 21 21 21
|
||||
15: TypeFloat 32
|
||||
16: TypeVector 15(float) 4
|
||||
17: TypePointer Function 16(fvec4)
|
||||
19: 15(float) Constant 1077936128
|
||||
20: 15(float) Constant 1082130432
|
||||
21: 15(float) Constant 1084227584
|
||||
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
|
||||
5: Label
|
||||
15(sample): 7(ptr) Variable Function
|
||||
Store 15(sample) 16
|
||||
Store 20(@entryPointOutput) 22
|
||||
18(sample): 17(ptr) Variable Function
|
||||
Store 18(sample) 23
|
||||
26: 16(fvec4) Load 18(sample)
|
||||
Store 25(@entryPointOutput) 26
|
||||
Return
|
||||
FunctionEnd
|
||||
10(sample(i1;): 6(int) Function None 8
|
||||
|
|
|
@ -12,7 +12,7 @@ float4 main() : SV_Target0
|
|||
{
|
||||
// HLSL allows this as an identifier as well.
|
||||
// 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",
|
||||
// so e.g, "int sample;" is accepted.
|
||||
if (peekTokenClass(EHTokSample)) {
|
||||
idToken.string = NewPoolTString("sample");
|
||||
idToken.tokenClass = EHTokIdentifier;
|
||||
idToken.symbol = nullptr;
|
||||
idToken.loc = token.loc;
|
||||
token.string = NewPoolTString("sample");
|
||||
token.tokenClass = EHTokIdentifier;
|
||||
token.symbol = nullptr;
|
||||
|
||||
idToken = token;
|
||||
advanceToken();
|
||||
return true;
|
||||
}
|
||||
|
@ -475,8 +476,15 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type)
|
|||
TSourceLoc loc = token.loc;
|
||||
|
||||
// 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;
|
||||
}
|
||||
if (type.getBasicType() == EbtBlock) {
|
||||
// the type was a block, which set some parts of the qualifier
|
||||
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
|
||||
|
@ -2203,7 +2211,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
|
|||
} else if (acceptIdentifier(idToken)) {
|
||||
// identifier or function_call name
|
||||
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)) {
|
||||
// function_call (nothing else to do yet)
|
||||
} else {
|
||||
|
|
Загрузка…
Ссылка в новой задаче