Added 32 bit integer output types

As long as there's no floating point arithmetic, 32 bit integer
types are computationally equivalent to 32 bit floating point.

Change-Id: I5ab19da440f52617a9bc64dff6fcaf8eff796aeb
Reviewed-on: https://swiftshader-review.googlesource.com/4717
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp
index 1396a52..ef335b8 100644
--- a/src/OpenGL/common/Image.cpp
+++ b/src/OpenGL/common/Image.cpp
@@ -500,6 +500,30 @@
 			return sw::FORMAT_A16F;
 		case GL_ALPHA32F_EXT:
 			return sw::FORMAT_A32F;
+		case GL_RED_INTEGER:
+			switch(type)
+			{
+			case GL_INT:          return sw::FORMAT_R32I;
+			case GL_UNSIGNED_INT: return sw::FORMAT_R32UI;
+			default: UNREACHABLE(type);
+			}
+			break;
+		case GL_RG_INTEGER:
+			switch(type)
+			{
+			case GL_INT:          return sw::FORMAT_G32R32I;
+			case GL_UNSIGNED_INT: return sw::FORMAT_G32R32UI;
+			default: UNREACHABLE(type);
+			}
+			break;
+		case GL_RGBA_INTEGER:
+			switch(type)
+			{
+			case GL_INT:          return sw::FORMAT_A32B32G32R32I;
+			case GL_UNSIGNED_INT: return sw::FORMAT_A32B32G32R32UI;
+			default: UNREACHABLE(type);
+			}
+			break;
 		default:
 			UNREACHABLE(format);
 		}
diff --git a/src/Shader/PixelProgram.cpp b/src/Shader/PixelProgram.cpp
index 41a0324..203387c 100644
--- a/src/Shader/PixelProgram.cpp
+++ b/src/Shader/PixelProgram.cpp
@@ -598,6 +598,12 @@
 			case FORMAT_R32F:
 			case FORMAT_G32R32F:
 			case FORMAT_A32B32G32R32F:
+			case FORMAT_R32I:
+			case FORMAT_G32R32I:
+			case FORMAT_A32B32G32R32I:
+			case FORMAT_R32UI:
+			case FORMAT_G32R32UI:
+			case FORMAT_A32B32G32R32UI:
 				for(unsigned int q = 0; q < state.multiSample; q++)
 				{
 					Pointer<Byte> buffer = cBuffer[index] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[index]));
@@ -697,6 +703,12 @@
 			case FORMAT_R32F:
 			case FORMAT_G32R32F:
 			case FORMAT_A32B32G32R32F:
+			case FORMAT_R32I:
+			case FORMAT_G32R32I:
+			case FORMAT_A32B32G32R32I:
+			case FORMAT_R32UI:
+			case FORMAT_G32R32UI:
+			case FORMAT_A32B32G32R32UI:
 				break;
 			default:
 				ASSERT(false);
diff --git a/src/Shader/PixelRoutine.cpp b/src/Shader/PixelRoutine.cpp
index 32a1f41..c43c87c 100644
--- a/src/Shader/PixelRoutine.cpp
+++ b/src/Shader/PixelRoutine.cpp
@@ -1961,8 +1961,27 @@
 		Short4 c01;
 		Short4 c23;
 
+		Float4 one;
 		switch(state.targetFormat[index])
 		{
+		case FORMAT_R32I:
+		case FORMAT_G32R32I:
+			one = As<Float4>(Int4(0x7FFFFFFF));
+			break;
+		case FORMAT_R32UI:
+		case FORMAT_G32R32UI:
+			one = As<Float4>(Int4(0xFFFFFFFF));
+			break;
+		case FORMAT_R32F:
+		case FORMAT_G32R32F:
+			one = Float4(1.0f);
+			break;
+		}
+
+		switch(state.targetFormat[index])
+		{
+		case FORMAT_R32I:
+		case FORMAT_R32UI:
 		case FORMAT_R32F:
 			buffer = cBuffer;
 			// FIXME: movlps
@@ -1972,10 +1991,10 @@
 			// FIXME: movhps
 			pixel.x.z = *Pointer<Float>(buffer + 4 * x + 0);
 			pixel.x.w = *Pointer<Float>(buffer + 4 * x + 4);
-			pixel.y = Float4(1.0f);
-			pixel.z = Float4(1.0f);
-			pixel.w = Float4(1.0f);
+			pixel.y = pixel.z = pixel.w = one;
 			break;
+		case FORMAT_G32R32I:
+		case FORMAT_G32R32UI:
 		case FORMAT_G32R32F:
 			buffer = cBuffer;
 			pixel.x = *Pointer<Float4>(buffer + 8 * x, 16);
@@ -1985,10 +2004,11 @@
 			pixel.x = ShuffleLowHigh(pixel.x, pixel.y, 0x88);
 			pixel.z = ShuffleLowHigh(pixel.z, pixel.y, 0xDD);
 			pixel.y = pixel.z;
-			pixel.z = Float4(1.0f);
-			pixel.w = Float4(1.0f);
+			pixel.z = pixel.w = one;
 			break;
 		case FORMAT_A32B32G32R32F:
+		case FORMAT_A32B32G32R32I:
+		case FORMAT_A32B32G32R32UI:
 			buffer = cBuffer;
 			pixel.x = *Pointer<Float4>(buffer + 16 * x, 16);
 			pixel.y = *Pointer<Float4>(buffer + 16 * x + 16, 16);
@@ -2123,14 +2143,20 @@
 		switch(state.targetFormat[index])
 		{
 		case FORMAT_R32F:
+		case FORMAT_R32I:
+		case FORMAT_R32UI:
 			break;
 		case FORMAT_G32R32F:
+		case FORMAT_G32R32I:
+		case FORMAT_G32R32UI:
 			oC.z = oC.x;
 			oC.x = UnpackLow(oC.x, oC.y);
 			oC.z = UnpackHigh(oC.z, oC.y);
 			oC.y = oC.z;
 			break;
 		case FORMAT_A32B32G32R32F:
+		case FORMAT_A32B32G32R32I:
+		case FORMAT_A32B32G32R32UI:
 			transpose4x4(oC.x, oC.y, oC.z, oC.w);
 			break;
 		default:
@@ -2161,6 +2187,8 @@
 		switch(state.targetFormat[index])
 		{
 		case FORMAT_R32F:
+		case FORMAT_R32I:
+		case FORMAT_R32UI:
 			if(rgbaWriteMask & 0x00000001)
 			{
 				buffer = cBuffer + 4 * x;
@@ -2191,6 +2219,8 @@
 			}
 			break;
 		case FORMAT_G32R32F:
+		case FORMAT_G32R32I:
+		case FORMAT_G32R32UI:
 			buffer = cBuffer + 8 * x;
 
 			value = *Pointer<Float4>(buffer);
@@ -2228,6 +2258,8 @@
 			*Pointer<Float4>(buffer) = oC.y;
 			break;
 		case FORMAT_A32B32G32R32F:
+		case FORMAT_A32B32G32R32I:
+		case FORMAT_A32B32G32R32UI:
 			buffer = cBuffer + 16 * x;
 
 			{