Enable glsl integer code

This cl enables true integer support in glsl shaders.
It still uses floating point registers to store all
registers, regardless of the type, so integer and
unsigned integer variables are simply reinterpreted
as integers or unsigned integers and used as such by
the appropriate instructions.

Change-Id: If62213c917b4b0c907e58db9cd36944dd198beaa
Reviewed-on: https://swiftshader-review.googlesource.com/3910
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/D3D9/D3D9.rc b/src/D3D9/D3D9.rc
index fbd29af..e927519 100644
--- a/src/D3D9/D3D9.rc
+++ b/src/D3D9/D3D9.rc
@@ -7,7 +7,7 @@
 //
 // Generated from the TEXTINCLUDE 2 resource.
 //
-#include "afxres.h"
+#include "windows.h"
 #include "../Common/Version.h"
 /////////////////////////////////////////////////////////////////////////////
 #undef APSTUDIO_READONLY_SYMBOLS
diff --git a/src/OpenGL/compiler/ConstantUnion.h b/src/OpenGL/compiler/ConstantUnion.h
index d1802c8..e6bec81 100644
--- a/src/OpenGL/compiler/ConstantUnion.h
+++ b/src/OpenGL/compiler/ConstantUnion.h
@@ -93,15 +93,16 @@
     float getFConst() const { return fConst; }
     bool getBConst() const { return bConst; }
 
-	float getAsFloat()
+	float getAsFloat() const
 	{
 		const int FFFFFFFFh = 0xFFFFFFFF;
 
 		switch(type)
 		{
-        case EbtInt:   return (float)iConst;
+        case EbtInt:   return reinterpret_cast<const float&>(iConst);
+		case EbtUInt:  return reinterpret_cast<const float&>(uConst);
         case EbtFloat: return fConst;
-		case EbtBool:  return (bConst == true) ? (float&)FFFFFFFFh : 0;
+		case EbtBool:  return (bConst == true) ? reinterpret_cast<const float&>(FFFFFFFFh) : 0;
         default:       return 0;
         }
 	}
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index e722baa..cc7d25e 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -166,6 +166,94 @@
 		free(temporaries, temporary);

 	}

 

+	sw::Shader::Opcode OutputASM::getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const

+	{

+		TBasicType baseType = in->getType().getBasicType();

+

+		switch(op)

+		{

+		case sw::Shader::OPCODE_NEG:

+			switch(baseType)

+			{

+			case EbtInt:

+			case EbtUInt:

+				return sw::Shader::OPCODE_INEG;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		case sw::Shader::OPCODE_ADD:

+			switch(baseType)

+			{

+			case EbtInt:

+			case EbtUInt:

+				return sw::Shader::OPCODE_IADD;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		case sw::Shader::OPCODE_SUB:

+			switch(baseType)

+			{

+			case EbtInt:

+			case EbtUInt:

+				return sw::Shader::OPCODE_ISUB;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		case sw::Shader::OPCODE_MUL:

+			switch(baseType)

+			{

+			case EbtInt:

+			case EbtUInt:

+				return sw::Shader::OPCODE_IMUL;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		case sw::Shader::OPCODE_DIV:

+			switch(baseType)

+			{

+			case EbtInt:

+				return sw::Shader::OPCODE_IDIV;

+			case EbtUInt:

+				return sw::Shader::OPCODE_UDIV;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		case sw::Shader::OPCODE_IMOD:

+			return baseType == EbtUInt ? sw::Shader::OPCODE_UMOD : op;

+		case sw::Shader::OPCODE_ISHR:

+			return baseType == EbtUInt ? sw::Shader::OPCODE_USHR : op;

+		case sw::Shader::OPCODE_MIN:

+			switch(baseType)

+			{

+			case EbtInt:

+				return sw::Shader::OPCODE_IMIN;

+			case EbtUInt:

+				return sw::Shader::OPCODE_UMIN;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		case sw::Shader::OPCODE_MAX:

+			switch(baseType)

+			{

+			case EbtInt:

+				return sw::Shader::OPCODE_IMAX;

+			case EbtUInt:

+				return sw::Shader::OPCODE_UMAX;

+			case EbtFloat:

+			default:

+				return op;

+			}

+		default:

+			return op;

+		}

+	}

+

 	void OutputASM::visitSymbol(TIntermSymbol *symbol)

 	{

 		// Vertex varyings don't have to be actively used to successfully link

@@ -375,23 +463,37 @@
 				mov->src[0].swizzle = swizzle;

 			}

 			break;

-		case EOpAddAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_ADD, result, left, left, right); break;

-		case EOpAdd:       if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_ADD, result, left, right);       break;

-		case EOpSubAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SUB, result, left, left, right); break;

-		case EOpSub:       if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_SUB, result, left, right);       break;

-		case EOpMulAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_MUL, result, left, left, right); break;

-		case EOpMul:       if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_MUL, result, left, right);       break;

-		case EOpDivAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_DIV, result, left, left, right); break;

-		case EOpDiv:       if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_DIV, result, left, right);       break;

+		case EOpAddAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, left, right); break;

+		case EOpAdd:       if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, right);       break;

+		case EOpSubAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, left, right); break;

+		case EOpSub:       if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, right);       break;

+		case EOpMulAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, left, right); break;

+		case EOpMul:       if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, right);       break;

+		case EOpDivAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, left, right); break;

+		case EOpDiv:       if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, right);       break;

+		case EOpIModAssign:          if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, left, right); break;

+		case EOpIMod:                if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, right);       break;

+		case EOpBitShiftLeftAssign:  if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SHL, result, left, left, right); break;

+		case EOpBitShiftLeft:        if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_SHL, result, left, right);       break;

+		case EOpBitShiftRightAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, left, right); break;

+		case EOpBitShiftRight:       if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, right);       break;

+		case EOpBitwiseAndAssign:    if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_AND, result, left, left, right); break;

+		case EOpBitwiseAnd:          if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_AND, result, left, right);       break;

+		case EOpBitwiseXorAssign:    if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_XOR, result, left, left, right); break;

+		case EOpBitwiseXor:          if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_XOR, result, left, right);       break;

+		case EOpBitwiseOrAssign:     if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_OR, result, left, left, right);  break;

+		case EOpBitwiseOr:           if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_OR, result, left, right);        break;

 		case EOpEqual:

 			if(visit == PostVisit)

 			{

-				emitCmp(sw::Shader::CONTROL_EQ, result, left, right);

+				emitBinary(sw::Shader::OPCODE_EQ, result, left, right);

 

 				for(int index = 1; index < left->totalRegisterCount(); index++)

 				{

 					Temporary equal(this);

-					emitCmp(sw::Shader::CONTROL_EQ, &equal, left, right, index);

+					Instruction *eq = emit(sw::Shader::OPCODE_EQ, &equal, left, right);

+					argument(eq->src[0], left, index);

+					argument(eq->src[1], right, index);

 					emit(sw::Shader::OPCODE_AND, result, result, &equal);

 				}

 			}

@@ -399,12 +501,14 @@
 		case EOpNotEqual:

 			if(visit == PostVisit)

 			{

-				emitCmp(sw::Shader::CONTROL_NE, result, left, right);

+				emitBinary(sw::Shader::OPCODE_NE, result, left, right);

 

 				for(int index = 1; index < left->totalRegisterCount(); index++)

 				{

 					Temporary notEqual(this);

-					emitCmp(sw::Shader::CONTROL_NE, &notEqual, left, right, index);

+					Instruction *eq = emit(sw::Shader::OPCODE_NE, &notEqual, left, right);

+					argument(eq->src[0], left, index);

+					argument(eq->src[1], right, index);

 					emit(sw::Shader::OPCODE_OR, result, result, &notEqual);

 				}

 			}

@@ -413,8 +517,8 @@
 		case EOpGreaterThan:             if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, left, right); break;

 		case EOpLessThanEqual:           if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, left, right); break;

 		case EOpGreaterThanEqual:        if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, left, right); break;

-		case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_MUL, result, left, left, right); break;

-		case EOpVectorTimesScalar:       if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, left, right); break;

+		case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, left, right); break;

+		case EOpVectorTimesScalar:       if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, right); break;

 		case EOpMatrixTimesScalar:

 			if(visit == PostVisit)

 			{

@@ -536,24 +640,40 @@
 			return false;

 		}

 

-		Constant one(1.0f, 1.0f, 1.0f, 1.0f);

-		Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f);

-		Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f);

-

 		TIntermTyped *result = node;

 		TIntermTyped *arg = node->getOperand();

+		TBasicType basicType = arg->getType().getBasicType();

+

+		union

+		{

+			float f;

+			int i;

+		} one_value;

+

+		if(basicType == EbtInt || basicType == EbtUInt)

+		{

+			one_value.i = 1;

+		}

+		else

+		{

+			one_value.f = 1.0f;

+		}

+

+		Constant one(one_value.f, one_value.f, one_value.f, one_value.f);

+		Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f);

+		Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f);

 

 		switch(node->getOp())

 		{

 		case EOpNegative:

 			if(visit == PostVisit)

 			{

+				sw::Shader::Opcode negOpcode = getOpcode(sw::Shader::OPCODE_NEG, arg);

 				for(int index = 0; index < arg->totalRegisterCount(); index++)

 				{

-					Instruction *neg = emit(sw::Shader::OPCODE_MOV, result, arg);

+					Instruction *neg = emit(negOpcode, result, arg);

 					neg->dst.index += index;

 					argument(neg->src[0], arg, index);

-					neg->src[0].modifier = sw::Shader::MODIFIER_NEGATE;

 				}

 			}

 			break;

@@ -564,9 +684,10 @@
 			{

 				copy(result, arg);

 

+				sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg);

 				for(int index = 0; index < arg->totalRegisterCount(); index++)

 				{

-					Instruction *add = emit(sw::Shader::OPCODE_ADD, arg, arg, &one);

+					Instruction *add = emit(addOpcode, arg, arg, &one);

 					add->dst.index += index;

 					argument(add->src[0], arg, index);

 				}

@@ -579,9 +700,10 @@
 			{

 				copy(result, arg);

 

+				sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg);

 				for(int index = 0; index < arg->totalRegisterCount(); index++)

 				{

-					Instruction *sub = emit(sw::Shader::OPCODE_SUB, arg, arg, &one);

+					Instruction *sub = emit(subOpcode, arg, arg, &one);

 					sub->dst.index += index;

 					argument(sub->src[0], arg, index);

 				}

@@ -592,9 +714,10 @@
 		case EOpPreIncrement:

 			if(visit == PostVisit)

 			{

+				sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg);

 				for(int index = 0; index < arg->totalRegisterCount(); index++)

 				{

-					Instruction *add = emit(sw::Shader::OPCODE_ADD, result, arg, &one);

+					Instruction *add = emit(addOpcode, result, arg, &one);

 					add->dst.index += index;

 					argument(add->src[0], arg, index);

 				}

@@ -605,9 +728,10 @@
 		case EOpPreDecrement:

 			if(visit == PostVisit)

 			{

+				sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg);

 				for(int index = 0; index < arg->totalRegisterCount(); index++)

 				{

-					Instruction *sub = emit(sw::Shader::OPCODE_SUB, result, arg, &one);

+					Instruction *sub = emit(subOpcode, result, arg, &one);

 					sub->dst.index += index;

 					argument(sub->src[0], arg, index);

 				}

@@ -1064,13 +1188,13 @@
 		case EOpMod:              if(visit == PostVisit) emit(sw::Shader::OPCODE_MOD, result, arg[0], arg[1]); break;

 		case EOpPow:              if(visit == PostVisit) emit(sw::Shader::OPCODE_POW, result, arg[0], arg[1]); break;

 		case EOpAtan:             if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN2, result, arg[0], arg[1]); break;

-		case EOpMin:              if(visit == PostVisit) emit(sw::Shader::OPCODE_MIN, result, arg[0], arg[1]); break;

-		case EOpMax:              if(visit == PostVisit) emit(sw::Shader::OPCODE_MAX, result, arg[0], arg[1]); break;

+		case EOpMin:              if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, arg[0], arg[1]); break;

+		case EOpMax:              if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]); break;

 		case EOpClamp:

 			if(visit == PostVisit)

 			{

-				emit(sw::Shader::OPCODE_MAX, result, arg[0], arg[1]);

-				emit(sw::Shader::OPCODE_MIN, result, result, arg[2]);

+				emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]);

+				emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, result, arg[2]);

 			}

 			break;

 		case EOpMix:         if(visit == PostVisit) emit(sw::Shader::OPCODE_LRP, result, arg[2], arg[1], arg[0]); break;

@@ -1391,18 +1515,44 @@
 

 	Instruction *OutputASM::emitCast(TIntermTyped *dst, TIntermTyped *src)

 	{

-		// Integers are implemented as float

-		if((dst->getBasicType() == EbtFloat || dst->getBasicType() == EbtInt) && src->getBasicType() == EbtBool)

+		switch(src->getBasicType())

 		{

-			return emit(sw::Shader::OPCODE_B2F, dst, src);

-		}

-		if(dst->getBasicType() == EbtBool && (src->getBasicType() == EbtFloat || src->getBasicType() == EbtInt))

-		{

-			return emit(sw::Shader::OPCODE_F2B, dst, src);

-		}

-		if(dst->getBasicType() == EbtInt && src->getBasicType() == EbtFloat)

-		{

-			return emit(sw::Shader::OPCODE_TRUNC, dst, src);

+		case EbtBool:

+			switch(dst->getBasicType())

+			{

+			case EbtInt:   return emit(sw::Shader::OPCODE_B2I, dst, src);

+			case EbtUInt:  return emit(sw::Shader::OPCODE_B2U, dst, src);

+			case EbtFloat: return emit(sw::Shader::OPCODE_B2F, dst, src);

+			default:       break;

+			}

+			break;

+		case EbtInt:

+			switch(dst->getBasicType())

+			{

+			case EbtBool:  return emit(sw::Shader::OPCODE_I2B, dst, src);

+			case EbtFloat: return emit(sw::Shader::OPCODE_I2F, dst, src);

+			default:       break;

+			}

+			break;

+		case EbtUInt:

+			switch(dst->getBasicType())

+			{

+			case EbtBool:  return emit(sw::Shader::OPCODE_U2B, dst, src);

+			case EbtFloat: return emit(sw::Shader::OPCODE_U2F, dst, src);

+			default:       break;

+			}

+			break;

+		case EbtFloat:

+			switch(dst->getBasicType())

+			{

+			case EbtBool: return emit(sw::Shader::OPCODE_F2B, dst, src);

+			case EbtInt:  return emit(sw::Shader::OPCODE_F2I, dst, src);

+			case EbtUInt: return emit(sw::Shader::OPCODE_F2U, dst, src);

+			default:      break;

+			}

+			break;

+		default:

+			break;

 		}

 

 		return emit(sw::Shader::OPCODE_MOV, dst, src);

@@ -1424,8 +1574,20 @@
 

 	void OutputASM::emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index)

 	{

-		bool boolean = (left->getAsTyped()->getBasicType() == EbtBool);

-		sw::Shader::Opcode opcode = boolean ? sw::Shader::OPCODE_ICMP : sw::Shader::OPCODE_CMP;

+		sw::Shader::Opcode opcode;

+		switch(left->getAsTyped()->getBasicType())

+		{

+		case EbtBool:

+		case EbtInt:

+			opcode = sw::Shader::OPCODE_ICMP;

+			break;

+		case EbtUInt:

+			opcode = sw::Shader::OPCODE_UCMP;

+			break;

+		default:

+			opcode = sw::Shader::OPCODE_CMP;

+			break;

+		}

 

 		Instruction *cmp = emit(opcode, dst, left, right);

 		cmp->control = cmpOp;

@@ -1745,19 +1907,19 @@
 							if(scale == 1)

 							{

 								Constant oldScale((int)dst.rel.scale);

-								Instruction *mad = emit(sw::Shader::OPCODE_MAD, &address, &address, &oldScale, right);

+								Instruction *mad = emit(sw::Shader::OPCODE_IMAD, &address, &address, &oldScale, right);

 								mad->src[0].index = dst.rel.index;

 								mad->src[0].type = dst.rel.type;

 							}

 							else

 							{

 								Constant oldScale((int)dst.rel.scale);

-								Instruction *mul = emit(sw::Shader::OPCODE_MUL, &address, &address, &oldScale);

+								Instruction *mul = emit(sw::Shader::OPCODE_IMUL, &address, &address, &oldScale);

 								mul->src[0].index = dst.rel.index;

 								mul->src[0].type = dst.rel.type;

 

 								Constant newScale(scale);

-								emit(sw::Shader::OPCODE_MAD, &address, right, &newScale, &address);

+								emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address);

 							}

 

 							dst.rel.type = sw::Shader::PARAMETER_TEMP;

@@ -1768,12 +1930,12 @@
 						{

 							if(scale == 1)

 							{

-								emit(sw::Shader::OPCODE_ADD, &address, &address, right);

+								emit(sw::Shader::OPCODE_IADD, &address, &address, right);

 							}

 							else

 							{

 								Constant newScale(scale);

-								emit(sw::Shader::OPCODE_MAD, &address, right, &newScale, &address);

+								emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address);

 							}

 						}

 					}

@@ -2210,7 +2372,6 @@
 	int OutputASM::attributeRegister(TIntermTyped *attribute)

 	{

 		ASSERT(!attribute->isArray());

-		ASSERT(attribute->getBasicType() == EbtFloat);

 

 		int index = lookup(attributes, attribute);

 

diff --git a/src/OpenGL/compiler/OutputASM.h b/src/OpenGL/compiler/OutputASM.h
index ccee01a..4e3a641 100644
--- a/src/OpenGL/compiler/OutputASM.h
+++ b/src/OpenGL/compiler/OutputASM.h
@@ -175,6 +175,7 @@
 		virtual bool visitLoop(Visit visit, TIntermLoop*);

 		virtual bool visitBranch(Visit visit, TIntermBranch*);

 

+		sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const;

 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, int index = 0);

 		Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src);

 		void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);

diff --git a/src/OpenGL/libGL/libGL.cpp b/src/OpenGL/libGL/libGL.cpp
index 9b4516a..0aa62f4 100644
--- a/src/OpenGL/libGL/libGL.cpp
+++ b/src/OpenGL/libGL/libGL.cpp
@@ -2994,9 +2994,9 @@
 	case GL_LOW_INT:

 	case GL_MEDIUM_INT:

 	case GL_HIGH_INT:

-		// Single-precision floating-point numbers can accurately represent integers up to +/-16777216

-		range[0] = 24;

-		range[1] = 24;

+		// Full integer precision is supported

+		range[0] = 31;

+		range[1] = 30;

 		*precision = 0;

 		break;

 	default:

diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 87209a1..6e4240d 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -169,7 +169,12 @@
         return mStride ? mStride : typeSize();

     }

 

-	inline float getCurrentValue(int i) const

+	inline float getCurrentValueBitsAsFloat(int i) const

+	{

+		return mCurrentValue[i].f;

+	}

+

+	inline float getCurrentValueF(int i) const

 	{

 		switch(mCurrentValueType)

 		{

diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp
index 13e7103..18fa089 100644
--- a/src/OpenGL/libGLESv2/Program.cpp
+++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -2192,11 +2192,11 @@
 

 	bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[i];

+			vector[i][0] = v[i];

 			vector[i][1] = 0;

 			vector[i][2] = 0;

 			vector[i][3] = 0;

@@ -2251,12 +2251,12 @@
 

 	bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[0];

-			vector[i][1] = (float)v[1];

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

 			vector[i][2] = 0;

 			vector[i][3] = 0;

 

@@ -2280,13 +2280,13 @@
 

 	bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[0];

-			vector[i][1] = (float)v[1];

-			vector[i][2] = (float)v[2];

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

+			vector[i][2] = v[2];

 			vector[i][3] = 0;

 

 			v += 3;

@@ -2309,14 +2309,14 @@
 

 	bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[0];

-			vector[i][1] = (float)v[1];

-			vector[i][2] = (float)v[2];

-			vector[i][3] = (float)v[3];

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

+			vector[i][2] = v[2];

+			vector[i][3] = v[3];

 

 			v += 4;

 		}

@@ -2338,11 +2338,11 @@
 

 	bool Program::applyUniform1uiv(GLint location, GLsizei count, const GLuint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLuint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[i];

+			vector[i][0] = v[i];

 			vector[i][1] = 0;

 			vector[i][2] = 0;

 			vector[i][3] = 0;

@@ -2397,12 +2397,12 @@
 

 	bool Program::applyUniform2uiv(GLint location, GLsizei count, const GLuint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLuint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[0];

-			vector[i][1] = (float)v[1];

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

 			vector[i][2] = 0;

 			vector[i][3] = 0;

 

@@ -2426,13 +2426,13 @@
 

 	bool Program::applyUniform3uiv(GLint location, GLsizei count, const GLuint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLuint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[0];

-			vector[i][1] = (float)v[1];

-			vector[i][2] = (float)v[2];

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

+			vector[i][2] = v[2];

 			vector[i][3] = 0;

 

 			v += 3;

@@ -2455,14 +2455,14 @@
 

 	bool Program::applyUniform4uiv(GLint location, GLsizei count, const GLuint *v)

 	{

-		float vector[MAX_UNIFORM_VECTORS][4];

+		GLuint vector[MAX_UNIFORM_VECTORS][4];

 

 		for(int i = 0; i < count; i++)

 		{

-			vector[i][0] = (float)v[0];

-			vector[i][1] = (float)v[1];

-			vector[i][2] = (float)v[2];

-			vector[i][3] = (float)v[3];

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

+			vector[i][2] = v[2];

+			vector[i][3] = v[3];

 

 			v += 4;

 		}

diff --git a/src/OpenGL/libGLESv2/VertexDataManager.cpp b/src/OpenGL/libGLESv2/VertexDataManager.cpp
index 7bda77f..51aa4fb 100644
--- a/src/OpenGL/libGLESv2/VertexDataManager.cpp
+++ b/src/OpenGL/libGLESv2/VertexDataManager.cpp
@@ -200,7 +200,7 @@
                 if(mDirtyCurrentValue[i])

                 {

                     delete mCurrentValueBuffer[i];

-                    mCurrentValueBuffer[i] = new ConstantVertexBuffer(attrib.getCurrentValue(0), attrib.getCurrentValue(1), attrib.getCurrentValue(2), attrib.getCurrentValue(3));

+                    mCurrentValueBuffer[i] = new ConstantVertexBuffer(attrib.getCurrentValueBitsAsFloat(0), attrib.getCurrentValueBitsAsFloat(1), attrib.getCurrentValueBitsAsFloat(2), attrib.getCurrentValueBitsAsFloat(3));

                     mDirtyCurrentValue[i] = false;

                 }

 

diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 2aea581..311037b 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -3582,9 +3582,9 @@
 	case GL_LOW_INT:

 	case GL_MEDIUM_INT:

 	case GL_HIGH_INT:

-		// Single-precision floating-point numbers can accurately represent integers up to +/-16777216

-		range[0] = 24;

-		range[1] = 24;

+		// Full integer precision is supported

+		range[0] = 31;

+		range[1] = 30;

 		*precision = 0;

 		break;

 	default:

@@ -4155,7 +4155,7 @@
 				const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];

 				for(int i = 0; i < 4; ++i)

 				{

-					params[i] = attrib.getCurrentValue(i);

+					params[i] = attrib.getCurrentValueF(i);

 				}

 			}

 			break;

@@ -4228,7 +4228,7 @@
 				const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];

 				for(int i = 0; i < 4; ++i)

 				{

-					float currentValue = attrib.getCurrentValue(i);

+					float currentValue = attrib.getCurrentValueF(i);

 					params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));

 				}

 			}

diff --git a/src/Shader/PixelProgram.cpp b/src/Shader/PixelProgram.cpp
index 415117d..9b5673d 100644
--- a/src/Shader/PixelProgram.cpp
+++ b/src/Shader/PixelProgram.cpp
@@ -760,7 +760,7 @@
 			}
 			else if(src.rel.type == Shader::PARAMETER_TEMP)
 			{
-				reg.x = As<Float4>(Int4(i) + RoundInt(r.rf[src.rel.index].x));
+				reg.x = As<Float4>(Int4(i) + As<Int4>(r.rf[src.rel.index].x));
 			}
 			return reg;
 		case Shader::PARAMETER_PREDICATE:   return reg; // Dummy
@@ -898,21 +898,21 @@
 
 		if(var.rel.type == Shader::PARAMETER_TEMP)
 		{
-			return RoundInt(Extract(r.rf[var.rel.index].x, 0)) * var.rel.scale;
+			return As<Int>(Extract(r.rf[var.rel.index].x, 0)) * var.rel.scale;
 		}
 		else if(var.rel.type == Shader::PARAMETER_INPUT)
 		{
-			return RoundInt(Extract(r.vf[var.rel.index].x, 0)) * var.rel.scale;
+			return As<Int>(Extract(r.vf[var.rel.index].x, 0)) * var.rel.scale;
 		}
 		else if(var.rel.type == Shader::PARAMETER_OUTPUT)
 		{
-			return RoundInt(Extract(r.oC[var.rel.index].x, 0)) * var.rel.scale;
+			return As<Int>(Extract(r.oC[var.rel.index].x, 0)) * var.rel.scale;
 		}
 		else if(var.rel.type == Shader::PARAMETER_CONST)
 		{
-			RValue<Float4> c = *Pointer<Float4>(r.data + OFFSET(DrawData, ps.c[var.rel.index]));
+			RValue<Int4> c = *Pointer<Int4>(r.data + OFFSET(DrawData, ps.c[var.rel.index]));
 
-			return RoundInt(Extract(c, 0)) * var.rel.scale;
+			return Extract(c, 0) * var.rel.scale;
 		}
 		else ASSERT(false);
 
diff --git a/src/Shader/ShaderCore.cpp b/src/Shader/ShaderCore.cpp
index 17659cf..406b038 100644
--- a/src/Shader/ShaderCore.cpp
+++ b/src/Shader/ShaderCore.cpp
@@ -583,11 +583,14 @@
 		}
 	}
 
-	void ShaderCore::mov(Vector4f &dst, const Vector4f &src, bool floorToInteger)
+	void ShaderCore::mov(Vector4f &dst, const Vector4f &src, bool integerDestination)
 	{
-		if(floorToInteger)
+		if(integerDestination)
 		{
-			dst.x = Floor(src.x);
+			dst.x = As<Float4>(RoundInt(src.x));
+			dst.y = As<Float4>(RoundInt(src.y));
+			dst.z = As<Float4>(RoundInt(src.z));
+			dst.w = As<Float4>(RoundInt(src.w));
 		}
 		else
 		{
diff --git a/src/Shader/ShaderCore.hpp b/src/Shader/ShaderCore.hpp
index 3432eab..c3308aa 100644
--- a/src/Shader/ShaderCore.hpp
+++ b/src/Shader/ShaderCore.hpp
@@ -238,7 +238,7 @@
 		typedef Shader::Control Control;

 

 	public:

-		void mov(Vector4f &dst, const Vector4f &src, bool floorToInteger = false);

+		void mov(Vector4f &dst, const Vector4f &src, bool integerDestination = false);

 		void neg(Vector4f &dst, const Vector4f &src);

 		void ineg(Vector4f &dst, const Vector4f &src);

 		void f2b(Vector4f &dst, const Vector4f &src);

diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index eaa5b12..35581af 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -188,7 +188,7 @@
 			case Shader::OPCODE_IMIN:       imin(d, s0, s1);                break;
 			case Shader::OPCODE_UMIN:       umin(d, s0, s1);                break;
 			case Shader::OPCODE_MOV:		mov(d, s0, integer);			break;
-			case Shader::OPCODE_MOVA:		mov(d, s0);						break;
+			case Shader::OPCODE_MOVA:       mov(d, s0, true);               break;
 			case Shader::OPCODE_NEG:        neg(d, s0);                     break;
 			case Shader::OPCODE_INEG:       ineg(d, s0);                    break;
 			case Shader::OPCODE_F2B:		f2b(d, s0);						break;
@@ -680,7 +680,7 @@
 			}
 			else if(src.rel.type == Shader::PARAMETER_TEMP)
 			{
-				reg.x = As<Float4>(Int4(i) + RoundInt(r.r[src.rel.index].x));
+				reg.x = As<Float4>(Int4(i) + As<Int4>(r.r[src.rel.index].x));
 			}
 			return reg;
 		case Shader::PARAMETER_OUTPUT:
@@ -694,7 +694,7 @@
 			}
 			break;
 		case Shader::PARAMETER_MISCTYPE:
-			reg.x = Float(r.instanceID);
+			reg.x = As<Float>(Int(r.instanceID));
 			return reg;
 		default:
 			ASSERT(false);
@@ -821,7 +821,7 @@
 				default: ASSERT(false);
 				}
 
-				Int4 index = Int4(i) + RoundInt(a) * Int4(src.rel.scale);
+				Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
 
 				index = Min(As<UInt4>(index), UInt4(256));   // Clamp to constant register range, c[256] = {0, 0, 0, 0}
 				
@@ -848,21 +848,21 @@
 
 		if(var.rel.type == Shader::PARAMETER_TEMP)
 		{
-			return RoundInt(Extract(r.r[var.rel.index].x, 0)) * var.rel.scale;
+			return As<Int>(Extract(r.r[var.rel.index].x, 0)) * var.rel.scale;
 		}
 		else if(var.rel.type == Shader::PARAMETER_INPUT)
 		{
-			return RoundInt(Extract(r.v[var.rel.index].x, 0)) * var.rel.scale;
+			return As<Int>(Extract(r.v[var.rel.index].x, 0)) * var.rel.scale;
 		}
 		else if(var.rel.type == Shader::PARAMETER_OUTPUT)
 		{
-			return RoundInt(Extract(r.o[var.rel.index].x, 0)) * var.rel.scale;
+			return As<Int>(Extract(r.o[var.rel.index].x, 0)) * var.rel.scale;
 		}
 		else if(var.rel.type == Shader::PARAMETER_CONST)
 		{
-			RValue<Float4> c = *Pointer<Float4>(r.data + OFFSET(DrawData,vs.c[var.rel.index]));
+			RValue<Int4> c = *Pointer<Int4>(r.data + OFFSET(DrawData, vs.c[var.rel.index]));
 
-			return RoundInt(Extract(c, 0)) * var.rel.scale;
+			return Extract(c, 0) * var.rel.scale;
 		}
 		else ASSERT(false);