Unsigned int GLSL parsing fixed
Unsigned integers in GLSL were being parsed using the regular
integer parser, so it was limited to INT_MAX. All values from
INT_MAX + 1 to UINT_MAX could not be parsed properly.
Also, added constant folding for the 4 bit conversion glsl
functions.
Fixes shader compilation issue in the Epic Zen Garden example:
https://s3.amazonaws.com/mozilla-games/ZenGarden/EpicZenGarden.html
(unfortunately, the screen is still black, so there are other
issues left)
Fixes WebGL 2 test: conformance2/glsl3/float-parsing.html
Change-Id: Iae52b2c8e083f0e1a22599e5a583297b9850444d
Reviewed-on: https://swiftshader-review.googlesource.com/16648
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Common/Math.hpp b/src/Common/Math.hpp
index bae3c12..dd2bc9c 100644
--- a/src/Common/Math.hpp
+++ b/src/Common/Math.hpp
@@ -74,6 +74,18 @@
b = t;
}
+ template <typename destType, typename sourceType>
+ destType bitCast(const sourceType &source)
+ {
+ union
+ {
+ sourceType s;
+ destType d;
+ } sd;
+ sd.s = source;
+ return sd.d;
+ }
+
inline int iround(float x)
{
return (int)floor(x + 0.5f);
diff --git a/src/OpenGL/compiler/Intermediate.cpp b/src/OpenGL/compiler/Intermediate.cpp
index 4293868..fbcb16b 100644
--- a/src/OpenGL/compiler/Intermediate.cpp
+++ b/src/OpenGL/compiler/Intermediate.cpp
@@ -1778,10 +1778,12 @@
//
TIntermConstantUnion *newNode = 0;
ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
+ TType type = getType();
+ TBasicType basicType = type.getBasicType();
for (size_t i = 0; i < objectSize; i++) {
switch(op) {
case EOpNegative:
- switch (getType().getBasicType()) {
+ switch (basicType) {
case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
default:
@@ -1790,7 +1792,7 @@
}
break;
case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
- switch (getType().getBasicType()) {
+ switch (basicType) {
case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1798,7 +1800,7 @@
}
break;
case EOpBitwiseNot:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
default:
@@ -1807,7 +1809,7 @@
}
break;
case EOpRadians:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1815,7 +1817,7 @@
}
break;
case EOpDegrees:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1823,7 +1825,7 @@
}
break;
case EOpSin:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(sinf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1831,7 +1833,7 @@
}
break;
case EOpCos:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(cosf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1839,7 +1841,7 @@
}
break;
case EOpTan:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(tanf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1847,7 +1849,7 @@
}
break;
case EOpAsin:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(asinf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1855,7 +1857,7 @@
}
break;
case EOpAcos:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(acosf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1863,7 +1865,7 @@
}
break;
case EOpAtan:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(atanf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1871,7 +1873,7 @@
}
break;
case EOpSinh:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(sinhf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1879,7 +1881,7 @@
}
break;
case EOpCosh:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(coshf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1887,7 +1889,7 @@
}
break;
case EOpTanh:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(tanhf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1895,7 +1897,7 @@
}
break;
case EOpAsinh:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(asinhf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1903,7 +1905,7 @@
}
break;
case EOpAcosh:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(acoshf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1911,7 +1913,7 @@
}
break;
case EOpAtanh:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(atanhf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1919,7 +1921,7 @@
}
break;
case EOpLog:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(logf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1927,7 +1929,7 @@
}
break;
case EOpLog2:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(sw::log2(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1935,7 +1937,7 @@
}
break;
case EOpExp:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(expf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1943,7 +1945,7 @@
}
break;
case EOpExp2:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(exp2f(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1951,7 +1953,7 @@
}
break;
case EOpSqrt:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(sqrtf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
@@ -1959,18 +1961,63 @@
}
break;
case EOpInverseSqrt:
- switch(getType().getBasicType()) {
+ switch(basicType) {
case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
return 0;
}
break;
+ case EOpFloatBitsToInt:
+ switch(basicType) {
+ case EbtFloat:
+ tempConstArray[i].setIConst(sw::bitCast<int>(unionArray[i].getFConst()));
+ type.setBasicType(EbtInt);
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+ return 0;
+ }
+ break;
+ break;
+ case EOpFloatBitsToUint:
+ switch(basicType) {
+ case EbtFloat:
+ tempConstArray[i].setUConst(sw::bitCast<unsigned int>(unionArray[i].getFConst()));
+ type.setBasicType(EbtUInt);
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+ return 0;
+ }
+ break;
+ case EOpIntBitsToFloat:
+ switch(basicType) {
+ case EbtInt:
+ tempConstArray[i].setFConst(sw::bitCast<float>(unionArray[i].getIConst()));
+ type.setBasicType(EbtFloat);
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+ return 0;
+ }
+ break;
+ case EOpUintBitsToFloat:
+ switch(basicType) {
+ case EbtUInt:
+ tempConstArray[i].setFConst(sw::bitCast<float>(unionArray[i].getUConst()));
+ type.setBasicType(EbtFloat);
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+ return 0;
+ }
+ break;
default:
return 0;
}
}
- newNode = new TIntermConstantUnion(tempConstArray, getType());
+ newNode = new TIntermConstantUnion(tempConstArray, type);
newNode->setLine(getLine());
return newNode;
}
diff --git a/src/OpenGL/compiler/glslang.l b/src/OpenGL/compiler/glslang.l
index cc40dc2..fdc3977 100644
--- a/src/OpenGL/compiler/glslang.l
+++ b/src/OpenGL/compiler/glslang.l
@@ -492,7 +492,7 @@
return 0;
}
- if (!atoi_clamp(yytext, &(yylval->lex.i)))
+ if (!atou_clamp(yytext, &(yylval->lex.u)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return UINTCONSTANT;
diff --git a/src/OpenGL/compiler/glslang_lex.cpp b/src/OpenGL/compiler/glslang_lex.cpp
index 55b6ffb..0cf1555 100644
--- a/src/OpenGL/compiler/glslang_lex.cpp
+++ b/src/OpenGL/compiler/glslang_lex.cpp
@@ -3724,7 +3724,7 @@
return 0;
}
- if (!atoi_clamp(yytext, &(yylval->lex.i)))
+ if (!atou_clamp(yytext, &(yylval->lex.u)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return UINTCONSTANT;
diff --git a/src/OpenGL/compiler/util.cpp b/src/OpenGL/compiler/util.cpp
index 2905c1d..bd9783c 100644
--- a/src/OpenGL/compiler/util.cpp
+++ b/src/OpenGL/compiler/util.cpp
@@ -32,3 +32,11 @@
*value = std::numeric_limits<int>::max();
return success;
}
+
+bool atou_clamp(const char *str, unsigned int *value)
+{
+ bool success = pp::numeric_lex_int(str, value);
+ if(!success)
+ *value = std::numeric_limits<unsigned int>::max();
+ return success;
+}
diff --git a/src/OpenGL/compiler/util.h b/src/OpenGL/compiler/util.h
index a5c4842..563407e 100644
--- a/src/OpenGL/compiler/util.h
+++ b/src/OpenGL/compiler/util.h
@@ -21,14 +21,18 @@
// atof_clamp is like atof but
// 1. it forces C locale, i.e. forcing '.' as decimal point.
-// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
+// 2. it sets the value to FLT_MAX if overflow happens.
// Return false if overflow happens.
bool atof_clamp(const char *str, float *value);
-// If overflow happens, clamp the value to INT_MIN or INT_MAX.
+// If overflow happens, value is set to INT_MAX.
// Return false if overflow happens.
bool atoi_clamp(const char *str, int *value);
+// If overflow happens, value is set to UINT_MAX.
+// Return false if overflow happens.
+bool atou_clamp(const char *str, unsigned int *value);
+
#ifdef __cplusplus
} // end extern "C"
#endif