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:
steve-lunarg
2016-12-18 17:51:14 -07:00
parent abf5057948
commit a64ed3eba0
3 changed files with 71 additions and 41 deletions

View File

@@ -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 {