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
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
*)
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
//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"
//
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;
}
// | 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))
// ;
if (acceptTokenClass(EHTokSemicolon)) {
- parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
+ node = parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
return true;
}
}
// expression
// : identifier
// | ( expression )
-// | type(...) // constructor
+// | type(...) // constructor
// | literal
-// | identifier + identifier
+// | identifier operator identifier // to be generalized to all expressions
//
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();
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;
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);
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
//
// 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("");
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);