HLSL: Attribute grammar and if-else grammar/productions.

This commit is contained in:
John Kessenich
2016-06-05 11:23:11 -06:00
parent 21472aee75
commit 0d2b6de45b
8 changed files with 456 additions and 8 deletions

View File

@@ -0,0 +1,57 @@
hlsl.attribute.frag
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:14 Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
0:2 Function Parameters:
0:2 'input' (temp 4-component vector of float)
0:? Sequence
0:11 Test condition and select (temp void)
0:11 Condition
0:11 Constant:
0:11 0 (const int)
0:11 true case is null
0:? Linker Objects
Linked fragment stage:
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:14 Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
0:2 Function Parameters:
0:2 'input' (temp 4-component vector of float)
0:? Sequence
0:11 Test condition and select (temp void)
0:11 Condition
0:11 Constant:
0:11 0 (const int)
0:11 true case is null
0:? Linker Objects
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 10
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Source HLSL 450
Name 4 "PixelShaderFunction"
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 1
7: 6(int) Constant 0
4(PixelShaderFunction): 2 Function None 3
5: Label
SelectionMerge 9 None
BranchConditional 7 8 9
8: Label
Branch 9
9: Label
Return
FunctionEnd

223
Test/baseResults/hlsl.if.frag.out Executable file
View File

@@ -0,0 +1,223 @@
hlsl.if.frag
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:29 Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
0:2 Function Parameters:
0:2 'input' (temp 4-component vector of float)
0:? Sequence
0:3 Test condition and select (temp void)
0:3 Condition
0:3 Compare Equal (temp bool)
0:3 'input' (temp 4-component vector of float)
0:3 'input' (temp 4-component vector of float)
0:3 true case
0:4 Branch: Return with expression
0:4 'input' (temp 4-component vector of float)
0:6 Test condition and select (temp void)
0:6 Condition
0:6 Compare Equal (temp bool)
0:6 'input' (temp 4-component vector of float)
0:6 'input' (temp 4-component vector of float)
0:6 true case
0:7 Branch: Return with expression
0:7 'input' (temp 4-component vector of float)
0:6 false case
0:9 Branch: Return with expression
0:9 Negate value (temp 4-component vector of float)
0:9 'input' (temp 4-component vector of float)
0:11 Test condition and select (temp void)
0:11 Condition
0:11 Compare Equal (temp bool)
0:11 'input' (temp 4-component vector of float)
0:11 'input' (temp 4-component vector of float)
0:11 true case is null
0:14 Test condition and select (temp void)
0:14 Condition
0:14 Compare Equal (temp bool)
0:14 'input' (temp 4-component vector of float)
0:14 'input' (temp 4-component vector of float)
0:14 true case is null
0:19 Test condition and select (temp void)
0:19 Condition
0:19 Compare Equal (temp bool)
0:19 'input' (temp 4-component vector of float)
0:19 'input' (temp 4-component vector of float)
0:19 true case
0:? Sequence
0:20 Branch: Return with expression
0:20 'input' (temp 4-component vector of float)
0:23 Test condition and select (temp void)
0:23 Condition
0:23 Compare Equal (temp bool)
0:23 'input' (temp 4-component vector of float)
0:23 'input' (temp 4-component vector of float)
0:23 true case
0:? Sequence
0:24 Branch: Return with expression
0:24 'input' (temp 4-component vector of float)
0:23 false case
0:? Sequence
0:26 Branch: Return with expression
0:26 Negate value (temp 4-component vector of float)
0:26 'input' (temp 4-component vector of float)
0:? Linker Objects
Linked fragment stage:
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:29 Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
0:2 Function Parameters:
0:2 'input' (temp 4-component vector of float)
0:? Sequence
0:3 Test condition and select (temp void)
0:3 Condition
0:3 Compare Equal (temp bool)
0:3 'input' (temp 4-component vector of float)
0:3 'input' (temp 4-component vector of float)
0:3 true case
0:4 Branch: Return with expression
0:4 'input' (temp 4-component vector of float)
0:6 Test condition and select (temp void)
0:6 Condition
0:6 Compare Equal (temp bool)
0:6 'input' (temp 4-component vector of float)
0:6 'input' (temp 4-component vector of float)
0:6 true case
0:7 Branch: Return with expression
0:7 'input' (temp 4-component vector of float)
0:6 false case
0:9 Branch: Return with expression
0:9 Negate value (temp 4-component vector of float)
0:9 'input' (temp 4-component vector of float)
0:11 Test condition and select (temp void)
0:11 Condition
0:11 Compare Equal (temp bool)
0:11 'input' (temp 4-component vector of float)
0:11 'input' (temp 4-component vector of float)
0:11 true case is null
0:14 Test condition and select (temp void)
0:14 Condition
0:14 Compare Equal (temp bool)
0:14 'input' (temp 4-component vector of float)
0:14 'input' (temp 4-component vector of float)
0:14 true case is null
0:19 Test condition and select (temp void)
0:19 Condition
0:19 Compare Equal (temp bool)
0:19 'input' (temp 4-component vector of float)
0:19 'input' (temp 4-component vector of float)
0:19 true case
0:? Sequence
0:20 Branch: Return with expression
0:20 'input' (temp 4-component vector of float)
0:23 Test condition and select (temp void)
0:23 Condition
0:23 Compare Equal (temp bool)
0:23 'input' (temp 4-component vector of float)
0:23 'input' (temp 4-component vector of float)
0:23 true case
0:? Sequence
0:24 Branch: Return with expression
0:24 'input' (temp 4-component vector of float)
0:23 false case
0:? Sequence
0:26 Branch: Return with expression
0:26 Negate value (temp 4-component vector of float)
0:26 'input' (temp 4-component vector of float)
0:? Linker Objects
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 64
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Source HLSL 450
Name 4 "PixelShaderFunction"
Name 9 "input"
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypePointer Function 7(fvec4)
12: TypeBool
13: TypeVector 12(bool) 4
4(PixelShaderFunction): 2 Function None 3
5: Label
9(input): 8(ptr) Variable Function
10: 7(fvec4) Load 9(input)
11: 7(fvec4) Load 9(input)
14: 13(bvec4) FOrdEqual 10 11
15: 12(bool) All 14
SelectionMerge 17 None
BranchConditional 15 16 17
16: Label
18: 7(fvec4) Load 9(input)
ReturnValue 18
17: Label
20: 7(fvec4) Load 9(input)
21: 7(fvec4) Load 9(input)
22: 13(bvec4) FOrdEqual 20 21
23: 12(bool) All 22
SelectionMerge 25 None
BranchConditional 23 24 28
24: Label
26: 7(fvec4) Load 9(input)
ReturnValue 26
28: Label
29: 7(fvec4) Load 9(input)
30: 7(fvec4) FNegate 29
ReturnValue 30
25: Label
32: 7(fvec4) Load 9(input)
33: 7(fvec4) Load 9(input)
34: 13(bvec4) FOrdEqual 32 33
35: 12(bool) All 34
SelectionMerge 37 None
BranchConditional 35 36 37
36: Label
Branch 37
37: Label
38: 7(fvec4) Load 9(input)
39: 7(fvec4) Load 9(input)
40: 13(bvec4) FOrdEqual 38 39
41: 12(bool) All 40
SelectionMerge 43 None
BranchConditional 41 42 43
42: Label
Branch 43
43: Label
44: 7(fvec4) Load 9(input)
45: 7(fvec4) Load 9(input)
46: 13(bvec4) FOrdEqual 44 45
47: 12(bool) All 46
SelectionMerge 49 None
BranchConditional 47 48 49
48: Label
50: 7(fvec4) Load 9(input)
ReturnValue 50
49: Label
52: 7(fvec4) Load 9(input)
53: 7(fvec4) Load 9(input)
54: 13(bvec4) FOrdEqual 52 53
55: 12(bool) All 54
SelectionMerge 57 None
BranchConditional 55 56 60
56: Label
58: 7(fvec4) Load 9(input)
ReturnValue 58
60: Label
61: 7(fvec4) Load 9(input)
62: 7(fvec4) FNegate 61
ReturnValue 62
57: Label
Return
FunctionEnd

13
Test/hlsl.attribute.frag Normal file
View File

@@ -0,0 +1,13 @@
float4 PixelShaderFunction(float4 input) : COLOR0
{
[unroll];
[];
[][][];
[unroll(4)];
[allow_uav_condition];
[unroll(4)] [allow_uav_condition];
[ loop ];
[fastopt];
[branch] if (0);
[flatten];
}

28
Test/hlsl.if.frag Normal file
View File

@@ -0,0 +1,28 @@
float4 PixelShaderFunction(float4 input) : COLOR0
{
if (input == input)
return input;
if (input == input)
return input;
else
return -input;
if (input == input)
;
if (input == input)
;
else
;
[flatten] if (input == input) {
return input;
}
if (input == input) {
return input;
} else {
return -input;
}
}

View File

@@ -73,9 +73,11 @@ INSTANTIATE_TEST_CASE_P(
ToSpirv, HlslCompileTest, ToSpirv, HlslCompileTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{ ::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.assoc.frag", "PixelShaderFunction"}, {"hlsl.assoc.frag", "PixelShaderFunction"},
{"hlsl.attribute.frag", "PixelShaderFunction"},
{"hlsl.cast.frag", "PixelShaderFunction"}, {"hlsl.cast.frag", "PixelShaderFunction"},
{"hlsl.float1.frag", "PixelShaderFunction"}, {"hlsl.float1.frag", "PixelShaderFunction"},
{"hlsl.float4.frag", "PixelShaderFunction"}, {"hlsl.float4.frag", "PixelShaderFunction"},
{"hlsl.if.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.frag", "PixelShaderFunction"}, {"hlsl.intrinsics.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.negative.frag", "PixelShaderFunction"}, {"hlsl.intrinsics.negative.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.negative.vert", "VertexShaderFunction"}, {"hlsl.intrinsics.negative.vert", "VertexShaderFunction"},

View File

@@ -434,7 +434,7 @@ bool HlslGrammar::acceptFunctionParameters(TFunction& function)
// RIGHT_PAREN // RIGHT_PAREN
if (! acceptTokenClass(EHTokRightParen)) { if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis"); expected(")");
return false; return false;
} }
@@ -485,6 +485,31 @@ bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& no
return false; return false;
} }
// Accept an expression with parenthesis around it, where
// the parenthesis ARE NOT expression parenthesis, but the
// syntactically required ones like in "if ( expression )"
//
// Note this one is not set up to be speculative; as it gives
// errors if not found.
//
bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
{
// LEFT_PAREN
if (! acceptTokenClass(EHTokLeftParen))
expected("(");
if (! acceptExpression(expression)) {
expected("expression");
return false;
}
// RIGHT_PAREN
if (! acceptTokenClass(EHTokRightParen))
expected(")");
return true;
}
// The top-level full expression recognizer. // The top-level full expression recognizer.
// //
// expression // expression
@@ -620,7 +645,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
TType castType; TType castType;
if (acceptType(castType)) { if (acceptType(castType)) {
if (! acceptTokenClass(EHTokRightParen)) { if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis"); expected(")");
return false; return false;
} }
@@ -699,7 +724,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
return false; return false;
} }
if (! acceptTokenClass(EHTokRightParen)) { if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis"); expected(")");
return false; return false;
} }
} else if (acceptLiteral(node)) { } else if (acceptLiteral(node)) {
@@ -838,7 +863,7 @@ bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
// RIGHT_PAREN // RIGHT_PAREN
if (! acceptTokenClass(EHTokRightParen)) { if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis"); expected(")");
return false; return false;
} }
@@ -896,6 +921,24 @@ bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
return acceptTokenClass(EHTokRightBrace); return acceptTokenClass(EHTokRightBrace);
} }
bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
{
parseContext.pushScope();
bool result = acceptNestedStatement(statement);
parseContext.popScope();
return result;
}
bool HlslGrammar::acceptNestedStatement(TIntermNode*& statement)
{
parseContext.nestStatement();
bool result = acceptStatement(statement);
parseContext.unnestStatement();
return result;
}
// statement // statement
// : attributes attributed_statement // : attributes attributed_statement
// //
@@ -965,7 +1008,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
// SEMICOLON (following an expression) // SEMICOLON (following an expression)
if (! acceptTokenClass(EHTokSemicolon)) { if (! acceptTokenClass(EHTokSemicolon)) {
expected("semicolon"); expected(";");
return false; return false;
} }
} }
@@ -989,12 +1032,86 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
// //
void HlslGrammar::acceptAttributes() void HlslGrammar::acceptAttributes()
{ {
// TODO // For now, accept the [ XXX(X) ] syntax, but drop.
// TODO: subset to correct set? Pass on?
do {
// LEFT_BRACKET?
if (! acceptTokenClass(EHTokLeftBracket))
return;
// attribute
if (peekTokenClass(EHTokIdentifier)) {
// 'token.string' is the attribute
advanceToken();
} else if (! peekTokenClass(EHTokRightBracket)) {
expected("identifier");
advanceToken();
} }
// (x)
if (acceptTokenClass(EHTokLeftParen)) {
TIntermTyped* node;
if (! acceptLiteral(node))
expected("literal");
// 'node' has the literal in it
if (! acceptTokenClass(EHTokRightParen))
expected(")");
}
// RIGHT_BRACKET
if (acceptTokenClass(EHTokRightBracket))
continue;
expected("]");
return;
} while (true);
}
// selection_statement
// : IF LEFT_PAREN expression RIGHT_PAREN statement
// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
//
bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement) bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
{ {
TSourceLoc loc = token.loc;
// IF
if (! acceptTokenClass(EHTokIf))
return false; return false;
// so that something declared in the condition is scoped to the lifetimes
// of the then-else statements
parseContext.pushScope();
// LEFT_PAREN expression RIGHT_PAREN
TIntermTyped* condition;
if (! acceptParenExpression(condition))
return false;
// create the child statements
TIntermNodePair thenElse = { nullptr, nullptr };
// then statement
if (! acceptScopedStatement(thenElse.node1)) {
expected("then statement");
return false;
}
// ELSE
if (acceptTokenClass(EHTokElse)) {
// else statement
if (! acceptScopedStatement(thenElse.node2)) {
expected("else statement");
return false;
}
}
// Put the pieces together
statement = intermediate.addSelection(condition, thenElse, loc);
parseContext.popScope();
return true;
} }
bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement) bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
@@ -1036,7 +1153,7 @@ bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
// SEMICOLON // SEMICOLON
if (! acceptTokenClass(EHTokSemicolon)) { if (! acceptTokenClass(EHTokSemicolon)) {
expected("semicolon"); expected(";");
return false; return false;
} }

View File

@@ -64,6 +64,7 @@ namespace glslang {
bool acceptFunctionParameters(TFunction&); bool acceptFunctionParameters(TFunction&);
bool acceptParameterDeclaration(TFunction&); bool acceptParameterDeclaration(TFunction&);
bool acceptFunctionDefinition(TFunction&, TIntermNode*&); bool acceptFunctionDefinition(TFunction&, TIntermNode*&);
bool acceptParenExpression(TIntermTyped*&);
bool acceptExpression(TIntermTyped*&); bool acceptExpression(TIntermTyped*&);
bool acceptAssignmentExpression(TIntermTyped*&); bool acceptAssignmentExpression(TIntermTyped*&);
bool acceptBinaryExpression(TIntermTyped*&, PrecedenceLevel); bool acceptBinaryExpression(TIntermTyped*&, PrecedenceLevel);
@@ -75,6 +76,8 @@ namespace glslang {
bool acceptLiteral(TIntermTyped*&); bool acceptLiteral(TIntermTyped*&);
bool acceptCompoundStatement(TIntermNode*&); bool acceptCompoundStatement(TIntermNode*&);
bool acceptStatement(TIntermNode*&); bool acceptStatement(TIntermNode*&);
bool acceptScopedStatement(TIntermNode*&);
bool acceptNestedStatement(TIntermNode*&);
void acceptAttributes(); void acceptAttributes();
bool acceptSelectionStatement(TIntermNode*&); bool acceptSelectionStatement(TIntermNode*&);
bool acceptSwitchStatement(TIntermNode*&); bool acceptSwitchStatement(TIntermNode*&);

View File

@@ -139,6 +139,11 @@ public:
void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index); void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
void nestStatement() { ++statementNestingLevel; }
void unnestStatement() { --statementNestingLevel; }
void pushScope() { symbolTable.push(); }
void popScope() { symbolTable.pop(0); }
protected: protected:
void inheritGlobalDefaults(TQualifier& dst) const; void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* makeInternalVariable(const char* name, const TType&) const; TVariable* makeInternalVariable(const char* name, const TType&) const;