diff --git a/Test/baseResults/constFold.frag.out b/Test/baseResults/constFold.frag.out index 8c014684..965c6dbc 100644 --- a/Test/baseResults/constFold.frag.out +++ b/Test/baseResults/constFold.frag.out @@ -179,7 +179,7 @@ ERROR: node is still EOpNull! 0:83 Constant: 0:83 2147483647 (const int) 0:84 Constant: -0:84 inf +0:84 +1.#INF 0:88 Constant: 0:88 2 (const uint) 0:88 3 (const uint) diff --git a/Test/baseResults/hlsl.inf.vert.out b/Test/baseResults/hlsl.inf.vert.out new file mode 100755 index 00000000..ef551e7f --- /dev/null +++ b/Test/baseResults/hlsl.inf.vert.out @@ -0,0 +1,172 @@ +hlsl.inf.vert +Shader version: 500 +0:? Sequence +0:2 Function Definition: @main( ( temp 4-component vector of float) +0:2 Function Parameters: +0:? Sequence +0:3 Sequence +0:3 move second child to first child ( temp float) +0:3 'f1' ( temp float) +0:3 Constant: +0:3 -1.#INF +0:4 Sequence +0:4 move second child to first child ( temp float) +0:4 'f2' ( temp float) +0:4 Constant: +0:4 +1.#INF +0:5 Sequence +0:5 move second child to first child ( temp float) +0:5 'f3' ( temp float) +0:5 Constant: +0:5 +1.#INF +0:6 Sequence +0:6 move second child to first child ( temp float) +0:6 'f4' ( temp float) +0:6 add ( temp float) +0:6 component-wise multiply ( temp float) +0:6 'f2' ( temp float) +0:6 Constant: +0:6 +1.#INF +0:6 Constant: +0:6 +1.#INF +0:10 Branch: Return with expression +0:10 Construct vec4 ( temp 4-component vector of float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 'f1' ( temp float) +0:10 'f2' ( temp float) +0:10 'f3' ( temp float) +0:10 'f4' ( temp float) +0:10 Constant: +0:10 -1.#INF +0:10 Constant: +0:10 1.#IND +0:2 Function Definition: main( ( temp void) +0:2 Function Parameters: +0:? Sequence +0:2 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:2 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' ( out 4-component vector of float Position) + + +Linked vertex stage: + + +Shader version: 500 +0:? Sequence +0:2 Function Definition: @main( ( temp 4-component vector of float) +0:2 Function Parameters: +0:? Sequence +0:3 Sequence +0:3 move second child to first child ( temp float) +0:3 'f1' ( temp float) +0:3 Constant: +0:3 -1.#INF +0:4 Sequence +0:4 move second child to first child ( temp float) +0:4 'f2' ( temp float) +0:4 Constant: +0:4 +1.#INF +0:5 Sequence +0:5 move second child to first child ( temp float) +0:5 'f3' ( temp float) +0:5 Constant: +0:5 +1.#INF +0:6 Sequence +0:6 move second child to first child ( temp float) +0:6 'f4' ( temp float) +0:6 add ( temp float) +0:6 component-wise multiply ( temp float) +0:6 'f2' ( temp float) +0:6 Constant: +0:6 +1.#INF +0:6 Constant: +0:6 +1.#INF +0:10 Branch: Return with expression +0:10 Construct vec4 ( temp 4-component vector of float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 add ( temp float) +0:10 'f1' ( temp float) +0:10 'f2' ( temp float) +0:10 'f3' ( temp float) +0:10 'f4' ( temp float) +0:10 Constant: +0:10 -1.#INF +0:10 Constant: +0:10 1.#IND +0:2 Function Definition: main( ( temp void) +0:2 Function Parameters: +0:? Sequence +0:2 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:2 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' ( out 4-component vector of float Position) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 37 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 35 + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 12 "f1" + Name 14 "f2" + Name 16 "f3" + Name 17 "f4" + Name 35 "@entryPointOutput" + Decorate 35(@entryPointOutput) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypePointer Function 6(float) + 13: 6(float) Constant 4286578688 + 15: 6(float) Constant 2139095040 + 29: 6(float) Constant 4290772992 + 34: TypePointer Output 7(fvec4) +35(@entryPointOutput): 34(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 36: 7(fvec4) FunctionCall 9(@main() + Store 35(@entryPointOutput) 36 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 12(f1): 11(ptr) Variable Function + 14(f2): 11(ptr) Variable Function + 16(f3): 11(ptr) Variable Function + 17(f4): 11(ptr) Variable Function + Store 12(f1) 13 + Store 14(f2) 15 + Store 16(f3) 15 + 18: 6(float) Load 14(f2) + 19: 6(float) FMul 18 15 + 20: 6(float) FAdd 19 15 + Store 17(f4) 20 + 21: 6(float) Load 12(f1) + 22: 6(float) Load 14(f2) + 23: 6(float) FAdd 21 22 + 24: 6(float) Load 16(f3) + 25: 6(float) FAdd 23 24 + 26: 6(float) Load 17(f4) + 27: 6(float) FAdd 25 26 + 28: 6(float) FAdd 27 13 + 30: 6(float) FAdd 28 29 + 31: 7(fvec4) CompositeConstruct 30 30 30 30 + ReturnValue 31 + FunctionEnd diff --git a/Test/hlsl.inf.vert b/Test/hlsl.inf.vert new file mode 100755 index 00000000..d57b8379 --- /dev/null +++ b/Test/hlsl.inf.vert @@ -0,0 +1,11 @@ +float4 main() : SV_Position +{ + float f1 = -1.#INF; + float f2 = 1.#INF; + float f3 = +1.#INF; + float f4 = f2 * 1.#INF + 1.#INF; + const float f5 = -1.#INF; + const float f6 = f5 * 0.0f; + + return (float4)(f1 + f2 + f3 + f4 + f5 + f6); +} \ No newline at end of file diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 5528dfe7..73ac8a61 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1994" -#define GLSLANG_DATE "11-Apr-2017" +#define GLSLANG_REVISION "Overload400-PrecQual.1995" +#define GLSLANG_DATE "12-Apr-2017" diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index c0c60c57..e5b555bb 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -45,11 +45,31 @@ namespace { -bool is_positive_infinity(double x) { +bool IsInfinity(double x) { #ifdef _MSC_VER - return _fpclass(x) == _FPCLASS_PINF; + switch (_fpclass(x)) { + case _FPCLASS_NINF: + case _FPCLASS_PINF: + return true; + default: + return false; + } #else - return std::isinf(x) && (x >= 0); + return std::isinf(x); +#endif +} + +bool IsNan(double x) { +#ifdef _MSC_VER + switch (_fpclass(x)) { + case _FPCLASS_SNAN: + case _FPCLASS_QNAN: + return true; + default: + return false; + } +#else + return std::isnan(x); #endif } @@ -694,11 +714,14 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const #endif { const double value = constUnion[i].getDConst(); - // Print infinity in a portable way, for test stability. - // Other cases may be needed in the future: negative infinity, - // and NaNs. - if (is_positive_infinity(value)) - out.debug << "inf\n"; + // Print infinities and NaNs in a portable way. + if (IsInfinity(value)) { + if (value < 0) + out.debug << "-1.#INF\n"; + else + out.debug << "+1.#INF\n"; + } else if (IsNan(value)) + out.debug << "1.#IND\n"; else { const int maxSize = 300; char buf[maxSize]; diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index f1c41abd..c14f22ea 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -92,7 +92,7 @@ namespace glslang { class TPpToken { public: - TPpToken() : space(false), ival(0), dval(0.0), i64val(0) + TPpToken() : space(false), i64val(0) { loc.init(); name[0] = 0; @@ -108,10 +108,14 @@ public: bool operator!=(const TPpToken& right) { return ! operator==(right); } TSourceLoc loc; - bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned - int ival; - double dval; - long long i64val; + bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned + + union { + int ival; + double dval; + long long i64val; + }; + char name[MaxTokenLength + 1]; }; diff --git a/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/glslang/MachineIndependent/preprocessor/PpScanner.cpp index dd162693..f711ad6a 100644 --- a/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ b/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -124,6 +124,35 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) HasDecimalOrExponent = true; saveName(ch); ch = getChar(); + + // 1.#INF or -1.#INF + if (ch == '#') { + if ((len < 2) || + (len == 2 && ppToken->name[0] != '1') || + (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) || + (len > 3)) + parseContext.ppError(ppToken->loc, "unexpected use of", "#", ""); + else { + // we have 1.# or -1.# or +1.#, check for 'INF' + if ((ch = getChar()) != 'I' || + (ch = getChar()) != 'N' || + (ch = getChar()) != 'F') + parseContext.ppError(ppToken->loc, "expected 'INF'", "#", ""); + else { + // we have [+-].#INF, and we are targeting IEEE 754, so wrap it up: + saveName('I'); + saveName('N'); + saveName('F'); + ppToken->name[len] = '\0'; + if (ppToken->name[0] == '-') + ppToken->i64val = 0xfff0000000000000; // -Infinity + else + ppToken->i64val = 0x7ff0000000000000; // +Infinity + return PpAtomConstFloat; + } + } + } + while (ch >= '0' && ch <= '9') { saveName(ch); ch = getChar(); diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 6bbc16b9..22368c18 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -134,6 +134,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.identifier.sample.frag", "main"}, {"hlsl.if.frag", "PixelShaderFunction"}, {"hlsl.implicitBool.frag", "main"}, + {"hlsl.inf.vert", "main"}, {"hlsl.inoutquals.frag", "main"}, {"hlsl.init.frag", "ShaderFunction"}, {"hlsl.init2.frag", "main"},