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
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:
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
// Generated by (magic number): 80001
// Id's are bound by 17

View File

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

View File

@ -66,7 +66,7 @@ while read t; do
*)
echo Running HLSL-to-SPIR-V $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
;;
esac

View File

@ -33,6 +33,23 @@
//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 "hlslGrammar.h"
@ -74,11 +91,21 @@ bool HlslGrammar::acceptTokenClass(EHlslTokenClass tokenClass)
//
bool HlslGrammar::acceptCompilationUnit()
{
TIntermNode* unitNode = nullptr;
while (token.tokenClass != EHTokNone) {
if (! acceptDeclaration())
// externalDeclaration
TIntermNode* declarationNode;
if (! acceptDeclaration(declarationNode))
return false;
// hook it up
unitNode = parseContext.intermediate.growAggregate(unitNode, declarationNode);
}
// set root of AST
parseContext.intermediate.setTreeRoot(unitNode);
return true;
}
@ -90,8 +117,13 @@ bool HlslGrammar::acceptCompilationUnit()
// | fully_specified_type identifier function_parameters ; // function prototype
// | 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
TType type;
if (! acceptFullySpecifiedType(type))
@ -114,7 +146,7 @@ bool HlslGrammar::acceptDeclaration()
// ;
if (acceptTokenClass(EHTokSemicolon)) {
parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
node = parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
return true;
}
}
@ -252,9 +284,9 @@ bool HlslGrammar::acceptType(TType& type)
// expression
// : identifier
// | ( expression )
// | type(...) // constructor
// | type(...) // constructor
// | literal
// | identifier + identifier
// | identifier operator identifier // to be generalized to all expressions
//
bool HlslGrammar::acceptExpression(TIntermTyped*& node)
{
@ -282,19 +314,11 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
if (acceptLiteral(node))
return true;
// type(...) // constructor
TType type;
if (acceptType(type)) {
TIntermSequence* arguments;
if (! acceptArguments(arguments)) {
expected("constructor arguments");
return false;
}
// type(...) // constructor
if (acceptConstructor(node))
return true;
}
// identifier + identifier
// identifier operator identifier
if (token.tokenClass == EHTokIdentifier) {
TIntermTyped* left = parseContext.handleVariable(token.loc, token.symbol, token.string);
advanceToken();
@ -318,22 +342,61 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
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
// : ( 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))
return false;
do {
// expression
TIntermTyped* arg;
if (! acceptExpression(arg))
break;
// hook it up
parseContext.handleFunctionArgument(function, arguments, arg);
// ,
if (! acceptTokenClass(EHTokComma))
break;
} while (true);
// )
if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis");
return false;

View File

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

View File

@ -754,6 +754,14 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
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
// - .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.
//
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);
if (op == EOpNull) {
error(loc, "cannot construct this type", type.getBasicString(), "");
op = EOpConstructFloat;
TType errorType(EbtFloat);
type.shallowCopy(errorType);
return nullptr;
}
TString empty("");

View File

@ -83,12 +83,13 @@ public:
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
void handleFunctionArgument(TFunction*, TIntermAggregate*&, TIntermTyped*);
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
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&);
void assignError(const TSourceLoc&, const char* op, TString left, TString right);