Implement float-integer conversions for ESSL 3.00

The implementation uses asint, asuint and asfloat in the HLSL output.

BUG=angle:865

Change-Id: I6b48298e18c7b3b0bdeac522b375ebc4eab7cf4e
Reviewed-on: https://chromium-review.googlesource.com/239520
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 043a251..93a2483 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -197,6 +197,31 @@
     symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float1, float1, float3);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float1, float1, float4);
 
+    TType *uint1 = new TType(EbtUInt);
+    TType *uint2 = new TType(EbtUInt, 2);
+    TType *uint3 = new TType(EbtUInt, 3);
+    TType *uint4 = new TType(EbtUInt, 4);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int1, "floatBitsToInt", float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "floatBitsToInt", float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "floatBitsToInt", float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int4, "floatBitsToInt", float4);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, uint1, "floatBitsToUint", float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, uint2, "floatBitsToUint", float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, uint3, "floatBitsToUint", float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, uint4, "floatBitsToUint", float4);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "intBitsToFloat", int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "intBitsToFloat", int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "intBitsToFloat", int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "intBitsToFloat", int4);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "uintBitsToFloat", uint1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "uintBitsToFloat", uint2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "uintBitsToFloat", uint3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "uintBitsToFloat", uint4);
+
     //
     // Geometric Functions.
     //
@@ -693,6 +718,11 @@
     symbolTable.relateToOperator(COMMON_BUILTINS, "step",         EOpStep);
     symbolTable.relateToOperator(COMMON_BUILTINS, "smoothstep",   EOpSmoothStep);
 
+    symbolTable.relateToOperator(ESSL3_BUILTINS, "floatBitsToInt",  EOpFloatBitsToInt);
+    symbolTable.relateToOperator(ESSL3_BUILTINS, "floatBitsToUint", EOpFloatBitsToUint);
+    symbolTable.relateToOperator(ESSL3_BUILTINS, "intBitsToFloat",  EOpIntBitsToFloat);
+    symbolTable.relateToOperator(ESSL3_BUILTINS, "uintBitsToFloat", EOpUintBitsToFloat);
+
     symbolTable.relateToOperator(COMMON_BUILTINS, "length",       EOpLength);
     symbolTable.relateToOperator(COMMON_BUILTINS, "distance",     EOpDistance);
     symbolTable.relateToOperator(COMMON_BUILTINS, "dot",          EOpDot);
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 3040470..782622f 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -332,6 +332,8 @@
       case EOpAny:
       case EOpAll:
       case EOpVectorLogicalNot:
+      case EOpIntBitsToFloat:
+      case EOpUintBitsToFloat:
         return true;
 
       default:
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 9b85aa2..58f676d 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -123,6 +123,11 @@
     EOpStep,
     EOpSmoothStep,
 
+    EOpFloatBitsToInt,
+    EOpFloatBitsToUint,
+    EOpIntBitsToFloat,
+    EOpUintBitsToFloat,
+
     EOpLength,
     EOpDistance,
     EOpDot,
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 6b01e49..256f3e4 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -467,6 +467,19 @@
         preString = "fract(";
         break;
 
+      case EOpFloatBitsToInt:
+        preString = "floatBitsToInt(";
+        break;
+      case EOpFloatBitsToUint:
+        preString = "floatBitsToUint(";
+        break;
+      case EOpIntBitsToFloat:
+        preString = "intBitsToFloat(";
+        break;
+      case EOpUintBitsToFloat:
+        preString = "uintBitsToFloat(";
+        break;
+
       case EOpLength:
         preString = "length(";
         break;
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 9445b09..0df2343 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1792,6 +1792,10 @@
       case EOpFloor:            outputTriplet(visit, "floor(", "", ")");     break;
       case EOpCeil:             outputTriplet(visit, "ceil(", "", ")");      break;
       case EOpFract:            outputTriplet(visit, "frac(", "", ")");      break;
+      case EOpFloatBitsToInt:   outputTriplet(visit, "asint(", "", ")");     break;
+      case EOpFloatBitsToUint:  outputTriplet(visit, "asuint(", "", ")");    break;
+      case EOpIntBitsToFloat:   outputTriplet(visit, "asfloat(", "", ")");   break;
+      case EOpUintBitsToFloat:  outputTriplet(visit, "asfloat(", "", ")");   break;
       case EOpLength:           outputTriplet(visit, "length(", "", ")");    break;
       case EOpNormalize:        outputTriplet(visit, "normalize(", "", ")"); break;
       case EOpDFdx:
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index 41c11cf..9677dc8 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -290,6 +290,11 @@
       case EOpCeil:           out << "Ceiling";              break;
       case EOpFract:          out << "Fraction";             break;
 
+      case EOpFloatBitsToInt: out << "float bits to int";    break;
+      case EOpFloatBitsToUint: out << "float bits to uint";  break;
+      case EOpIntBitsToFloat: out << "int bits to float";    break;
+      case EOpUintBitsToFloat: out << "uint bits to float";  break;
+
       case EOpLength:         out << "length";               break;
       case EOpNormalize:      out << "normalize";            break;
       // case EOpDPdx:           out << "dPdx";                 break;