HLSL: Hook up constructor expressions through the AST.

This commit is contained in:
John Kessenich 2016-03-13 11:24:20 -06:00
parent 87142c71fb
commit d016be19fb
7 changed files with 139 additions and 29 deletions

View File

@ -1,8 +1,50 @@
hlsl.frag hlsl.frag
Shader version: 100
gl_FragCoord origin is upper left
0:? Sequence
0:5 move second child to first child (temp 4-component vector of float)
0:5 'AmbientColor' (temp 4-component vector of float)
0:? Constant:
0:? 1.000000
0:? 0.500000
0:? 0.000000
0:? 1.000000
0:6 move second child to first child (temp float)
0:6 'AmbientIntensity' (temp float)
0:6 Constant:
0:6 0.100000
0:? Linker Objects
0:? 'World' (temp 4X4 matrix of float)
0:? 'View' (temp 4X4 matrix of float)
0:? 'Projection' (temp 4X4 matrix of float)
0:? 'AmbientColor' (temp 4-component vector of float)
0:? 'AmbientIntensity' (temp float)
Linked fragment stage: Linked fragment stage:
Shader version: 100
gl_FragCoord origin is upper left
0:? Sequence
0:5 move second child to first child (temp 4-component vector of float)
0:5 'AmbientColor' (temp 4-component vector of float)
0:? Constant:
0:? 1.000000
0:? 0.500000
0:? 0.000000
0:? 1.000000
0:6 move second child to first child (temp float)
0:6 'AmbientIntensity' (temp float)
0:6 Constant:
0:6 0.100000
0:? Linker Objects
0:? 'World' (temp 4X4 matrix of float)
0:? 'View' (temp 4X4 matrix of float)
0:? 'Projection' (temp 4X4 matrix of float)
0:? 'AmbientColor' (temp 4-component vector of float)
0:? 'AmbientIntensity' (temp float)
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 17 // Id's are bound by 17

View File

@ -2,7 +2,7 @@ float4x4 World;
float4x4 View; float4x4 View;
float4x4 Projection; float4x4 Projection;
float4 AmbientColor = float4(1, 1, 1, 1); float4 AmbientColor = float4(1, 0.5, 0, 1);
float AmbientIntensity = 0.1; float AmbientIntensity = 0.1;
//float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 //float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0

View File

@ -66,7 +66,7 @@ while read t; do
*) *)
echo Running HLSL-to-SPIR-V $t... echo Running HLSL-to-SPIR-V $t...
b=`basename $t` b=`basename $t`
$EXE -D -e PixelShaderFunction -H $t > $TARGETDIR/$b.out $EXE -D -e PixelShaderFunction -H -i $t > $TARGETDIR/$b.out
diff -b $BASEDIR/$b.out $TARGETDIR/$b.out || HASERROR=1 diff -b $BASEDIR/$b.out $TARGETDIR/$b.out || HASERROR=1
;; ;;
esac esac

View File

@ -33,6 +33,23 @@
//POSSIBILITY OF SUCH DAMAGE. //POSSIBILITY OF SUCH DAMAGE.
// //
//
// This is a set of mutually recursive methods implementing the HLSL grammar.
// Generally, each returns
// - through an argument: a type specifically appropriate to which rule it
// recognized
// - through the return value: true/false to indicate whether or not it
// recognized its rule
//
// As much as possible, only grammar recognition should happen in this file,
// with all other work being farmed out to hlslParseHelper.cpp, which it turn
// will build the AST.
//
// The next token, yet to be "accepted" is always sitting in 'token'.
// When a method says it accepts a rule, that means all tokens involved
// in the rule will have been consumed, and none left in 'token'.
//
#include "hlslTokens.h" #include "hlslTokens.h"
#include "hlslGrammar.h" #include "hlslGrammar.h"
@ -74,11 +91,21 @@ bool HlslGrammar::acceptTokenClass(EHlslTokenClass tokenClass)
// //
bool HlslGrammar::acceptCompilationUnit() bool HlslGrammar::acceptCompilationUnit()
{ {
TIntermNode* unitNode = nullptr;
while (token.tokenClass != EHTokNone) { while (token.tokenClass != EHTokNone) {
if (! acceptDeclaration()) // externalDeclaration
TIntermNode* declarationNode;
if (! acceptDeclaration(declarationNode))
return false; return false;
// hook it up
unitNode = parseContext.intermediate.growAggregate(unitNode, declarationNode);
} }
// set root of AST
parseContext.intermediate.setTreeRoot(unitNode);
return true; return true;
} }
@ -90,8 +117,13 @@ bool HlslGrammar::acceptCompilationUnit()
// | fully_specified_type identifier function_parameters ; // function prototype // | fully_specified_type identifier function_parameters ; // function prototype
// | fully_specified_type function_parameters compound_statement // function definition // | fully_specified_type function_parameters compound_statement // function definition
// //
bool HlslGrammar::acceptDeclaration() // 'node' could get created if the declaration creates code, like an initializer
// or a function body.
//
bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
{ {
node = nullptr;
// fully_specified_type // fully_specified_type
TType type; TType type;
if (! acceptFullySpecifiedType(type)) if (! acceptFullySpecifiedType(type))
@ -114,7 +146,7 @@ bool HlslGrammar::acceptDeclaration()
// ; // ;
if (acceptTokenClass(EHTokSemicolon)) { if (acceptTokenClass(EHTokSemicolon)) {
parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode); node = parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
return true; return true;
} }
} }
@ -252,9 +284,9 @@ bool HlslGrammar::acceptType(TType& type)
// expression // expression
// : identifier // : identifier
// | ( expression ) // | ( expression )
// | type(...) // constructor // | type(...) // constructor
// | literal // | literal
// | identifier + identifier // | identifier operator identifier // to be generalized to all expressions
// //
bool HlslGrammar::acceptExpression(TIntermTyped*& node) bool HlslGrammar::acceptExpression(TIntermTyped*& node)
{ {
@ -282,19 +314,11 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
if (acceptLiteral(node)) if (acceptLiteral(node))
return true; return true;
// type(...) // constructor // type(...) // constructor
TType type; if (acceptConstructor(node))
if (acceptType(type)) {
TIntermSequence* arguments;
if (! acceptArguments(arguments)) {
expected("constructor arguments");
return false;
}
return true; return true;
}
// identifier + identifier // identifier operator identifier
if (token.tokenClass == EHTokIdentifier) { if (token.tokenClass == EHTokIdentifier) {
TIntermTyped* left = parseContext.handleVariable(token.loc, token.symbol, token.string); TIntermTyped* left = parseContext.handleVariable(token.loc, token.symbol, token.string);
advanceToken(); advanceToken();
@ -318,22 +342,61 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
return true; return true;
} }
// constructor
// : type arguments
//
bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
{
// type
TType type;
if (acceptType(type)) {
TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
if (constructorFunction == nullptr)
return false;
// arguments
TIntermAggregate* arguments = nullptr;
if (! acceptArguments(constructorFunction, arguments)) {
expected("constructor arguments");
return false;
}
// hook it up
node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
return true;
}
return false;
}
// arguments // arguments
// : ( expression , expression, ... ) // : ( expression , expression, ... )
// //
bool HlslGrammar::acceptArguments(TIntermSequence*& arguments) // The arguments are pushed onto the 'function' argument list and
// onto the 'arguments' aggregate.
//
bool HlslGrammar::acceptArguments(TFunction* function, TIntermAggregate*& arguments)
{ {
// (
if (! acceptTokenClass(EHTokLeftParen)) if (! acceptTokenClass(EHTokLeftParen))
return false; return false;
do { do {
// expression
TIntermTyped* arg; TIntermTyped* arg;
if (! acceptExpression(arg)) if (! acceptExpression(arg))
break; break;
// hook it up
parseContext.handleFunctionArgument(function, arguments, arg);
// ,
if (! acceptTokenClass(EHTokComma)) if (! acceptTokenClass(EHTokComma))
break; break;
} while (true); } while (true);
// )
if (! acceptTokenClass(EHTokRightParen)) { if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis"); expected("right parenthesis");
return false; return false;

View File

@ -55,13 +55,14 @@ namespace glslang {
bool acceptTokenClass(EHlslTokenClass); bool acceptTokenClass(EHlslTokenClass);
bool acceptCompilationUnit(); bool acceptCompilationUnit();
bool acceptDeclaration(); bool acceptDeclaration(TIntermNode*& node);
bool acceptFullySpecifiedType(TType&); bool acceptFullySpecifiedType(TType&);
void acceptQualifier(TQualifier&); void acceptQualifier(TQualifier&);
bool acceptType(TType&); bool acceptType(TType&);
bool acceptCompoundStatement(); bool acceptCompoundStatement();
bool acceptExpression(TIntermTyped*&); bool acceptExpression(TIntermTyped*&);
bool acceptArguments(TIntermSequence*&); bool acceptConstructor(TIntermTyped*&);
bool acceptArguments(TFunction*, TIntermAggregate*&);
bool acceptLiteral(TIntermTyped*&); bool acceptLiteral(TIntermTyped*&);
bool acceptOperator(TOperator& op); bool acceptOperator(TOperator& op);

View File

@ -754,6 +754,14 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
return paramNodes; return paramNodes;
} }
void HlslParseContext::handleFunctionArgument(TFunction* function, TIntermAggregate*& arguments, TIntermTyped* arg)
{
TParameter param = { 0, new TType };
param.type->shallowCopy(arg->getType());
function->addParameter(param);
arguments = intermediate.growAggregate(arguments, arg);
}
// //
// Handle seeing function call syntax in the grammar, which could be any of // Handle seeing function call syntax in the grammar, which could be any of
// - .length() method // - .length() method
@ -1182,18 +1190,13 @@ void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fn
// //
// Handle seeing a built-in constructor in a grammar production. // Handle seeing a built-in constructor in a grammar production.
// //
TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType) TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const TType& type)
{ {
TType type(publicType);
type.getQualifier().precision = EpqNone;
TOperator op = mapTypeToConstructorOp(type); TOperator op = mapTypeToConstructorOp(type);
if (op == EOpNull) { if (op == EOpNull) {
error(loc, "cannot construct this type", type.getBasicString(), ""); error(loc, "cannot construct this type", type.getBasicString(), "");
op = EOpConstructFloat; return nullptr;
TType errorType(EbtFloat);
type.shallowCopy(errorType);
} }
TString empty(""); TString empty("");

View File

@ -83,12 +83,13 @@ public:
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
void handleFunctionArgument(TFunction*, TIntermAggregate*&, TIntermTyped*);
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&); bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
void assignError(const TSourceLoc&, const char* op, TString left, TString right); void assignError(const TSourceLoc&, const char* op, TString left, TString right);