mirror of
https://github.com/RPCS3/glslang.git
synced 2025-02-12 22:38:35 +00:00
HLSL: Add basic declaration syntax and AST generation.
This commit is contained in:
parent
e01a9bc8c0
commit
87142c71fb
@ -5,7 +5,7 @@ Linked fragment stage:
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 6
|
||||
// Id's are bound by 17
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
@ -14,8 +14,24 @@ Linked fragment stage:
|
||||
ExecutionMode 4 OriginUpperLeft
|
||||
Source HLSL 100
|
||||
Name 4 "PixelShaderFunction"
|
||||
Name 10 "World"
|
||||
Name 11 "View"
|
||||
Name 12 "Projection"
|
||||
Name 14 "AmbientColor"
|
||||
Name 16 "AmbientIntensity"
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeFloat 32
|
||||
7: TypeVector 6(float) 4
|
||||
8: TypeMatrix 7(fvec4) 4
|
||||
9: TypePointer Function 8
|
||||
13: TypePointer Function 7(fvec4)
|
||||
15: TypePointer Function 6(float)
|
||||
4(PixelShaderFunction): 2 Function None 3
|
||||
5: Label
|
||||
10(World): 9(ptr) Variable Function
|
||||
11(View): 9(ptr) Variable Function
|
||||
12(Projection): 9(ptr) Variable Function
|
||||
14(AmbientColor): 13(ptr) Variable Function
|
||||
16(AmbientIntensity): 15(ptr) Variable Function
|
||||
FunctionEnd
|
||||
|
@ -1,11 +1,11 @@
|
||||
//float4x4 World;
|
||||
//float4x4 View;
|
||||
//float4x4 Projection;
|
||||
//
|
||||
//float4 AmbientColor = float4(1, 1, 1, 1);
|
||||
//float AmbientIntensity = 0.1;
|
||||
//
|
||||
//float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
|
||||
//{
|
||||
// return AmbientColor * AmbientIntensity;
|
||||
//}
|
||||
float4x4 World;
|
||||
float4x4 View;
|
||||
float4x4 Projection;
|
||||
|
||||
float4 AmbientColor = float4(1, 1, 1, 1);
|
||||
float AmbientIntensity = 0.1;
|
||||
|
||||
//float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
|
||||
//{
|
||||
// return AmbientColor * AmbientIntensity;
|
||||
//}
|
||||
|
@ -83,11 +83,308 @@ bool HlslGrammar::acceptCompilationUnit()
|
||||
}
|
||||
|
||||
// declaration
|
||||
// : dummy stub
|
||||
// : SEMICOLON
|
||||
// : fully_specified_type ;
|
||||
// | fully_specified_type identifier ;
|
||||
// | fully_specified_type identifier = expression ;
|
||||
// | fully_specified_type identifier function_parameters ; // function prototype
|
||||
// | fully_specified_type function_parameters compound_statement // function definition
|
||||
//
|
||||
bool HlslGrammar::acceptDeclaration()
|
||||
{
|
||||
advanceToken();
|
||||
// fully_specified_type
|
||||
TType type;
|
||||
if (! acceptFullySpecifiedType(type))
|
||||
return false;
|
||||
|
||||
// identifier
|
||||
if (token.tokenClass == EHTokIdentifier) {
|
||||
TSourceLoc declLoc = token.loc;
|
||||
TString* declName = token.string;
|
||||
advanceToken();
|
||||
|
||||
// = expression
|
||||
TIntermTyped* expressionNode = nullptr;
|
||||
if (acceptTokenClass(EHTokEqual)) {
|
||||
if (! acceptExpression(expressionNode)) {
|
||||
expected("initializer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ;
|
||||
if (acceptTokenClass(EHTokSemicolon)) {
|
||||
parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// no identifier, just ;
|
||||
if (acceptTokenClass(EHTokSemicolon))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// fully_specified_type
|
||||
// : type_specifier
|
||||
// | type_qualifier type_specifier
|
||||
//
|
||||
bool HlslGrammar::acceptFullySpecifiedType(TType& type)
|
||||
{
|
||||
// type_qualifier
|
||||
TQualifier qualifier;
|
||||
qualifier.clear();
|
||||
acceptQualifier(qualifier);
|
||||
|
||||
// type_specifier
|
||||
if (! acceptType(type))
|
||||
return false;
|
||||
type.getQualifier() = qualifier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If token is a qualifier, return its token class and advance to the next
|
||||
// qualifier. Otherwise, return false, and don't advance.
|
||||
void HlslGrammar::acceptQualifier(TQualifier& qualifier)
|
||||
{
|
||||
switch (token.tokenClass) {
|
||||
case EHTokUniform:
|
||||
qualifier.storage = EvqUniform;
|
||||
break;
|
||||
case EHTokConst:
|
||||
qualifier.storage = EvqConst;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
advanceToken();
|
||||
}
|
||||
|
||||
// If token is for a type, update 'type' with the type information,
|
||||
// and return true and advance.
|
||||
// Otherwise, return false, and don't advance
|
||||
bool HlslGrammar::acceptType(TType& type)
|
||||
{
|
||||
if (! token.isType)
|
||||
return false;
|
||||
|
||||
switch (token.tokenClass) {
|
||||
case EHTokInt:
|
||||
case EHTokInt1:
|
||||
case EHTokDword:
|
||||
new(&type) TType(EbtInt);
|
||||
break;
|
||||
case EHTokFloat:
|
||||
case EHTokFloat1:
|
||||
new(&type) TType(EbtFloat);
|
||||
break;
|
||||
|
||||
case EHTokFloat2:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 2);
|
||||
break;
|
||||
case EHTokFloat3:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 3);
|
||||
break;
|
||||
case EHTokFloat4:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 4);
|
||||
break;
|
||||
|
||||
case EHTokInt2:
|
||||
new(&type) TType(EbtInt, EvqTemporary, 2);
|
||||
break;
|
||||
case EHTokInt3:
|
||||
new(&type) TType(EbtInt, EvqTemporary, 3);
|
||||
break;
|
||||
case EHTokInt4:
|
||||
new(&type) TType(EbtInt, EvqTemporary, 4);
|
||||
break;
|
||||
|
||||
case EHTokBool2:
|
||||
new(&type) TType(EbtBool, EvqTemporary, 2);
|
||||
break;
|
||||
case EHTokBool3:
|
||||
new(&type) TType(EbtBool, EvqTemporary, 3);
|
||||
break;
|
||||
case EHTokBool4:
|
||||
new(&type) TType(EbtBool, EvqTemporary, 4);
|
||||
break;
|
||||
|
||||
case EHTokFloat2x2:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
|
||||
break;
|
||||
case EHTokFloat2x3:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
|
||||
break;
|
||||
case EHTokFloat2x4:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
|
||||
break;
|
||||
case EHTokFloat3x2:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
|
||||
break;
|
||||
case EHTokFloat3x3:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
|
||||
break;
|
||||
case EHTokFloat3x4:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
|
||||
break;
|
||||
case EHTokFloat4x2:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
|
||||
break;
|
||||
case EHTokFloat4x3:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
|
||||
break;
|
||||
case EHTokFloat4x4:
|
||||
new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
advanceToken();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// expression
|
||||
// : identifier
|
||||
// | ( expression )
|
||||
// | type(...) // constructor
|
||||
// | literal
|
||||
// | identifier + identifier
|
||||
//
|
||||
bool HlslGrammar::acceptExpression(TIntermTyped*& node)
|
||||
{
|
||||
// identifier
|
||||
if (token.tokenClass == EHTokIdentifier) {
|
||||
node = parseContext.handleVariable(token.loc, token.symbol, token.string);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ( expression )
|
||||
if (acceptTokenClass(EHTokLeftParen)) {
|
||||
if (! acceptExpression(node)) {
|
||||
expected("expression");
|
||||
return false;
|
||||
}
|
||||
if (! acceptTokenClass(EHTokRightParen)) {
|
||||
expected("right parenthesis");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// literal
|
||||
if (acceptLiteral(node))
|
||||
return true;
|
||||
|
||||
// type(...) // constructor
|
||||
TType type;
|
||||
if (acceptType(type)) {
|
||||
TIntermSequence* arguments;
|
||||
if (! acceptArguments(arguments)) {
|
||||
expected("constructor arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// identifier + identifier
|
||||
if (token.tokenClass == EHTokIdentifier) {
|
||||
TIntermTyped* left = parseContext.handleVariable(token.loc, token.symbol, token.string);
|
||||
advanceToken();
|
||||
|
||||
// operator
|
||||
TOperator op;
|
||||
if (! acceptOperator(op))
|
||||
return false;
|
||||
TSourceLoc loc = token.loc;
|
||||
|
||||
// right
|
||||
if (token.tokenClass == EHTokIdentifier) {
|
||||
TIntermTyped* right = parseContext.handleVariable(token.loc, token.symbol, token.string);
|
||||
advanceToken();
|
||||
node = parseContext.intermediate.addBinaryMath(op, left, right, loc);
|
||||
} else
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// arguments
|
||||
// : ( expression , expression, ... )
|
||||
//
|
||||
bool HlslGrammar::acceptArguments(TIntermSequence*& arguments)
|
||||
{
|
||||
if (! acceptTokenClass(EHTokLeftParen))
|
||||
return false;
|
||||
|
||||
do {
|
||||
TIntermTyped* arg;
|
||||
if (! acceptExpression(arg))
|
||||
break;
|
||||
if (! acceptTokenClass(EHTokComma))
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
if (! acceptTokenClass(EHTokRightParen)) {
|
||||
expected("right parenthesis");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
|
||||
{
|
||||
switch (token.tokenClass) {
|
||||
case EHTokIntConstant:
|
||||
node = parseContext.intermediate.addConstantUnion(token.i, token.loc, true);
|
||||
break;
|
||||
case EHTokFloatConstant:
|
||||
node = parseContext.intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
|
||||
break;
|
||||
case EHTokDoubleConstant:
|
||||
node = parseContext.intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
|
||||
break;
|
||||
case EHTokBoolConstant:
|
||||
node = parseContext.intermediate.addConstantUnion(token.b, token.loc, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
advanceToken();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HlslGrammar::acceptOperator(TOperator& op)
|
||||
{
|
||||
switch (token.tokenClass) {
|
||||
case EHTokPlus:
|
||||
op = EOpAdd;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
advanceToken();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HlslGrammar::acceptCompoundStatement()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
@ -56,6 +56,14 @@ namespace glslang {
|
||||
|
||||
bool acceptCompilationUnit();
|
||||
bool acceptDeclaration();
|
||||
bool acceptFullySpecifiedType(TType&);
|
||||
void acceptQualifier(TQualifier&);
|
||||
bool acceptType(TType&);
|
||||
bool acceptCompoundStatement();
|
||||
bool acceptExpression(TIntermTyped*&);
|
||||
bool acceptArguments(TIntermSequence*&);
|
||||
bool acceptLiteral(TIntermTyped*&);
|
||||
bool acceptOperator(TOperator& op);
|
||||
|
||||
HlslScanContext& scanContext;
|
||||
HlslParseContext& parseContext;
|
||||
|
Loading…
x
Reference in New Issue
Block a user