mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 12:00:05 +00:00
HLSL: 1) Implement lookahead buffers/stacks for token advance/recede, 2) use it for cast operation.
The grammar now accepts type casts, like "(int)x", but that has to be disambiguated from "(a + b)", needed deeper lookahead and backing up than what existed so far.
This commit is contained in:
parent
080cdc1737
commit
1cc1a2813e
86
Test/baseResults/hlsl.cast.frag.out
Executable file
86
Test/baseResults/hlsl.cast.frag.out
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
hlsl.cast.frag
|
||||||
|
Shader version: 450
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:5 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 Branch: Return with expression
|
||||||
|
0:3 add (temp 4-component vector of float)
|
||||||
|
0:3 add (temp 4-component vector of float)
|
||||||
|
0:3 Construct vec4 (temp 4-component vector of float)
|
||||||
|
0:3 'input' (temp 4-component vector of float)
|
||||||
|
0:3 Convert int to float (temp 4-component vector of float)
|
||||||
|
0:3 Convert float to int (temp 4-component vector of int)
|
||||||
|
0:3 'input' (temp 4-component vector of float)
|
||||||
|
0:3 Constant:
|
||||||
|
0:3 1.198000
|
||||||
|
0:3 1.198000
|
||||||
|
0:3 1.198000
|
||||||
|
0:3 1.198000
|
||||||
|
0:? Linker Objects
|
||||||
|
|
||||||
|
|
||||||
|
Linked fragment stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 450
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:5 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 Branch: Return with expression
|
||||||
|
0:3 add (temp 4-component vector of float)
|
||||||
|
0:3 add (temp 4-component vector of float)
|
||||||
|
0:3 Construct vec4 (temp 4-component vector of float)
|
||||||
|
0:3 'input' (temp 4-component vector of float)
|
||||||
|
0:3 Convert int to float (temp 4-component vector of float)
|
||||||
|
0:3 Convert float to int (temp 4-component vector of int)
|
||||||
|
0:3 'input' (temp 4-component vector of float)
|
||||||
|
0:3 Constant:
|
||||||
|
0:3 1.198000
|
||||||
|
0:3 1.198000
|
||||||
|
0:3 1.198000
|
||||||
|
0:3 1.198000
|
||||||
|
0:? Linker Objects
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 26
|
||||||
|
|
||||||
|
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)
|
||||||
|
17: TypeInt 32 1
|
||||||
|
18: TypeVector 17(int) 4
|
||||||
|
22: 6(float) Constant 1067014160
|
||||||
|
23: 7(fvec4) ConstantComposite 22 22 22 22
|
||||||
|
4(PixelShaderFunction): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
9(input): 8(ptr) Variable Function
|
||||||
|
10: 7(fvec4) Load 9(input)
|
||||||
|
11: 6(float) CompositeExtract 10 0
|
||||||
|
12: 6(float) CompositeExtract 10 1
|
||||||
|
13: 6(float) CompositeExtract 10 2
|
||||||
|
14: 6(float) CompositeExtract 10 3
|
||||||
|
15: 7(fvec4) CompositeConstruct 11 12 13 14
|
||||||
|
16: 7(fvec4) Load 9(input)
|
||||||
|
19: 18(ivec4) ConvertFToS 16
|
||||||
|
20: 7(fvec4) ConvertSToF 19
|
||||||
|
21: 7(fvec4) FAdd 15 20
|
||||||
|
24: 7(fvec4) FAdd 21 23
|
||||||
|
ReturnValue 24
|
||||||
|
FunctionEnd
|
4
Test/hlsl.cast.frag
Normal file
4
Test/hlsl.cast.frag
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
float4 PixelShaderFunction(float4 input) : COLOR0
|
||||||
|
{
|
||||||
|
return (float4)input + (int4)input + (float4)1.198;
|
||||||
|
}
|
@ -73,6 +73,7 @@ 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.cast.frag", "PixelShaderFunction"},
|
||||||
{"hlsl.float1.frag", "PixelShaderFunction"},
|
{"hlsl.float1.frag", "PixelShaderFunction"},
|
||||||
{"hlsl.float4.frag", "PixelShaderFunction"},
|
{"hlsl.float4.frag", "PixelShaderFunction"},
|
||||||
{"hlsl.intrinsics.frag", "PixelShaderFunction"},
|
{"hlsl.intrinsics.frag", "PixelShaderFunction"},
|
||||||
|
@ -602,7 +602,8 @@ bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unary_expression
|
// unary_expression
|
||||||
// : + unary_expression
|
// : (type) unary_expression
|
||||||
|
// | + unary_expression
|
||||||
// | - unary_expression
|
// | - unary_expression
|
||||||
// | ! unary_expression
|
// | ! unary_expression
|
||||||
// | ~ unary_expression
|
// | ~ unary_expression
|
||||||
@ -612,9 +613,46 @@ bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel pr
|
|||||||
//
|
//
|
||||||
bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
|
bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
|
||||||
{
|
{
|
||||||
|
// (type) unary_expression
|
||||||
|
// Have to look two steps ahead, because this could be, e.g., a
|
||||||
|
// postfix_expression instead, since that also starts with at "(".
|
||||||
|
if (acceptTokenClass(EHTokLeftParen)) {
|
||||||
|
TType castType;
|
||||||
|
if (acceptType(castType)) {
|
||||||
|
if (! acceptTokenClass(EHTokRightParen)) {
|
||||||
|
expected("right parenthesis");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We've matched "(type)" now, get the expression to cast
|
||||||
|
TSourceLoc loc = token.loc;
|
||||||
|
if (! acceptUnaryExpression(node))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Hook it up like a constructor
|
||||||
|
TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
|
||||||
|
if (constructorFunction == nullptr) {
|
||||||
|
expected("type that can be constructed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TIntermTyped* arguments = nullptr;
|
||||||
|
parseContext.handleFunctionArgument(constructorFunction, arguments, node);
|
||||||
|
node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// This isn't a type cast, but it still started "(", so if it is a
|
||||||
|
// unary expression, it can only be a postfix_expression, so try that.
|
||||||
|
// Back it up first.
|
||||||
|
recedeToken();
|
||||||
|
return acceptPostfixExpression(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek for "op unary_expression"
|
||||||
TOperator unaryOp = HlslOpMap::preUnary(peek());
|
TOperator unaryOp = HlslOpMap::preUnary(peek());
|
||||||
|
|
||||||
// postfix_expression
|
// postfix_expression (if no unary operator)
|
||||||
if (unaryOp == EOpNull)
|
if (unaryOp == EOpNull)
|
||||||
return acceptPostfixExpression(node);
|
return acceptPostfixExpression(node);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ struct HlslToken {
|
|||||||
HlslToken() : isType(false), string(nullptr), symbol(nullptr) { loc.init(); }
|
HlslToken() : isType(false), string(nullptr), symbol(nullptr) { loc.init(); }
|
||||||
TSourceLoc loc; // location of token in the source
|
TSourceLoc loc; // location of token in the source
|
||||||
EHlslTokenClass tokenClass; // what kind of token it is
|
EHlslTokenClass tokenClass; // what kind of token it is
|
||||||
bool isType; // true if the token represents a user type
|
bool isType; // true if the token represents a type
|
||||||
union { // what data the token holds
|
union { // what data the token holds
|
||||||
glslang::TString *string; // for identifiers
|
glslang::TString *string; // for identifiers
|
||||||
int i; // for literals
|
int i; // for literals
|
||||||
|
@ -37,10 +37,45 @@
|
|||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
|
void HlslTokenStream::pushPreToken(const HlslToken& tok)
|
||||||
|
{
|
||||||
|
assert(preTokenStackSize == 0);
|
||||||
|
preTokenStack = tok;
|
||||||
|
++preTokenStackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
HlslToken HlslTokenStream::popPreToken()
|
||||||
|
{
|
||||||
|
assert(preTokenStackSize == 1);
|
||||||
|
--preTokenStackSize;
|
||||||
|
|
||||||
|
return preTokenStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HlslTokenStream::pushTokenBuffer(const HlslToken& tok)
|
||||||
|
{
|
||||||
|
tokenBuffer = tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
HlslToken HlslTokenStream::popTokenBuffer()
|
||||||
|
{
|
||||||
|
return tokenBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
// Load 'token' with the next token in the stream of tokens.
|
// Load 'token' with the next token in the stream of tokens.
|
||||||
void HlslTokenStream::advanceToken()
|
void HlslTokenStream::advanceToken()
|
||||||
{
|
{
|
||||||
scanner.tokenize(token);
|
pushTokenBuffer(token);
|
||||||
|
if (preTokenStackSize > 0)
|
||||||
|
token = popPreToken();
|
||||||
|
else
|
||||||
|
scanner.tokenize(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HlslTokenStream::recedeToken()
|
||||||
|
{
|
||||||
|
pushPreToken(token);
|
||||||
|
token = popTokenBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the current token class.
|
// Return the current token class.
|
||||||
|
@ -43,20 +43,38 @@ namespace glslang {
|
|||||||
class HlslTokenStream {
|
class HlslTokenStream {
|
||||||
public:
|
public:
|
||||||
explicit HlslTokenStream(HlslScanContext& scanner)
|
explicit HlslTokenStream(HlslScanContext& scanner)
|
||||||
: scanner(scanner) { }
|
: scanner(scanner), preTokenStackSize(0) { }
|
||||||
virtual ~HlslTokenStream() { }
|
virtual ~HlslTokenStream() { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void advanceToken();
|
void advanceToken();
|
||||||
|
void recedeToken();
|
||||||
bool acceptTokenClass(EHlslTokenClass);
|
bool acceptTokenClass(EHlslTokenClass);
|
||||||
EHlslTokenClass peek() const;
|
EHlslTokenClass peek() const;
|
||||||
bool peekTokenClass(EHlslTokenClass) const;
|
bool peekTokenClass(EHlslTokenClass) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HlslToken token; // the current token we are processing
|
HlslToken token; // the token we are currently looking at, but have not yet accepted
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HlslScanContext& scanner; // lexical scanner, to get next token
|
HlslScanContext& scanner; // lexical scanner, to get next token
|
||||||
|
|
||||||
|
// Previously scanned tokens, returned for future advances,
|
||||||
|
// so logically in front of the token stream.
|
||||||
|
// Is logically a stack; needs last in last out semantics.
|
||||||
|
// Currently implemented as a stack of size 1.
|
||||||
|
HlslToken preTokenStack;
|
||||||
|
int preTokenStackSize;
|
||||||
|
void pushPreToken(const HlslToken&);
|
||||||
|
HlslToken popPreToken();
|
||||||
|
|
||||||
|
// Previously scanned tokens, not yet return for future advances,
|
||||||
|
// but available for that.
|
||||||
|
// Is logically a fifo for normal advances, and a stack for recession.
|
||||||
|
// Currently implemented with an intrinsic size of 1.
|
||||||
|
HlslToken tokenBuffer;
|
||||||
|
void pushTokenBuffer(const HlslToken&);
|
||||||
|
HlslToken popTokenBuffer();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
Loading…
Reference in New Issue
Block a user