gl_InstanceID implementation

I need some help connecting the dots here.
I can see a few ways of doing it, but it
isn't trivial for me to see which one
would be right. Could you tell me how the
value should go from the VertexProcessor to
being assigned a value in the actual shader.

Change-Id: Ie0bc2024f51a904ab8144c435b623cfefe8e6704
Reviewed-on: https://swiftshader-review.googlesource.com/2920
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/BaseTypes.h b/src/OpenGL/compiler/BaseTypes.h
index a7dfe00..7e25c40 100644
--- a/src/OpenGL/compiler/BaseTypes.h
+++ b/src/OpenGL/compiler/BaseTypes.h
@@ -132,6 +132,7 @@
     // built-ins written by vertex shader
     EvqPosition,
     EvqPointSize,
+    EvqInstanceID,
 
     // built-ins read by fragment shader
     EvqFragCoord,
@@ -199,6 +200,7 @@
     case EvqOutput:         return "output";         break;
     case EvqPosition:       return "Position";       break;
     case EvqPointSize:      return "PointSize";      break;
+    case EvqInstanceID:     return "InstanceID";     break;
     case EvqFragCoord:      return "FragCoord";      break;
     case EvqFrontFacing:    return "FrontFacing";    break;
     case EvqFragColor:      return "FragColor";      break;
diff --git a/src/OpenGL/compiler/Compiler.cpp b/src/OpenGL/compiler/Compiler.cpp
index 5bb5865..1023a11 100644
--- a/src/OpenGL/compiler/Compiler.cpp
+++ b/src/OpenGL/compiler/Compiler.cpp
@@ -47,6 +47,10 @@
     MaxTextureImageUnits = 8;
     MaxFragmentUniformVectors = 16;
     MaxDrawBuffers = 1;
+    MaxVertexOutputVectors = 16;

+    MaxFragmentInputVectors = 15;

+    MinProgramTexelOffset = -8;

+    MaxProgramTexelOffset = 7;
 
     // Extensions.
     OES_standard_derivatives = 0;
diff --git a/src/OpenGL/compiler/Compiler.h b/src/OpenGL/compiler/Compiler.h
index b0fa548..9c0814e 100644
--- a/src/OpenGL/compiler/Compiler.h
+++ b/src/OpenGL/compiler/Compiler.h
@@ -39,6 +39,10 @@
     int MaxTextureImageUnits;
     int MaxFragmentUniformVectors;
     int MaxDrawBuffers;
+    int MaxVertexOutputVectors;
+    int MaxFragmentInputVectors;
+    int MinProgramTexelOffset;
+    int MaxProgramTexelOffset;
 
     // Extensions.
     // Set to 1 to enable the extension, else 0.
diff --git a/src/OpenGL/compiler/Initialize.cpp b/src/OpenGL/compiler/Initialize.cpp
index 61cf8d9..afcd561 100644
--- a/src/OpenGL/compiler/Initialize.cpp
+++ b/src/OpenGL/compiler/Initialize.cpp
@@ -319,6 +319,10 @@
     symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
     symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors);
     symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", resources.MaxVertexOutputVectors);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", resources.MaxFragmentInputVectors);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", resources.MinProgramTexelOffset);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", resources.MaxProgramTexelOffset);
 }
 
 void IdentifyBuiltIns(GLenum shaderType,
@@ -341,6 +345,7 @@
     case GL_VERTEX_SHADER:
         symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition,    4)));
         symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize,   1)));
+        symbolTable.insert(ESSL3_BUILTINS, *new TVariable(NewPoolTString("gl_InstanceID"), TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
         break;
     default: assert(false && "Language not supported");
     }
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index bd1cc5d..c2a42b6 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -1866,6 +1866,7 @@
 		case EvqConstReadOnly:       return sw::Shader::PARAMETER_TEMP;

 		case EvqPosition:            return sw::Shader::PARAMETER_OUTPUT;

 		case EvqPointSize:           return sw::Shader::PARAMETER_OUTPUT;

+		case EvqInstanceID:          return sw::Shader::PARAMETER_MISCTYPE;

 		case EvqFragCoord:           return sw::Shader::PARAMETER_MISCTYPE;

 		case EvqFrontFacing:         return sw::Shader::PARAMETER_MISCTYPE;

 		case EvqPointCoord:          return sw::Shader::PARAMETER_INPUT;

@@ -1901,6 +1902,7 @@
 		case EvqConstReadOnly:       return temporaryRegister(operand);

 		case EvqPosition:            return varyingRegister(operand);

 		case EvqPointSize:           return varyingRegister(operand);

+		case EvqInstanceID:          vertexShader->instanceIdDeclared = true; return 0;

 		case EvqFragCoord:           pixelShader->vPosDeclared = true;  return 0;

 		case EvqFrontFacing:         pixelShader->vFaceDeclared = true; return 1;

 		case EvqPointCoord:          return varyingRegister(operand);

diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index 2d9b3d5..4fda827 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -323,6 +323,7 @@
     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
     case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
+    case EvqInstanceID:     message = "can't modify gl_InstanceID";  break;
     default:
 
         //
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index f658447..e01e430 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3536,6 +3536,8 @@
 

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

 	{

+		device->setInstanceID(i);

+

 		GLenum err = applyVertexBuffer(0, first, count, i);

 		if(err != GL_NO_ERROR)

 		{

@@ -3589,6 +3591,8 @@
 

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

 	{

+		device->setInstanceID(i);

+

 		TranslatedIndexData indexInfo;

 		GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo);

 		if(err != GL_NO_ERROR)

diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index fe881c1..b01776b 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -81,7 +81,11 @@
     MAX_DRAW_BUFFERS = 1,

 	MAX_ELEMENT_INDEX = 0x7FFFFFFF,

 	MAX_ELEMENTS_INDICES = 0x7FFFFFFF,

-	MAX_ELEMENTS_VERTICES = 0x7FFFFFFF

+	MAX_ELEMENTS_VERTICES = 0x7FFFFFFF,

+    MAX_VERTEX_OUTPUT_VECTORS = 16,

+    MAX_FRAGMENT_INPUT_VECTORS = 15,

+    MIN_PROGRAM_TEXEL_OFFSET = -8,

+    MAX_PROGRAM_TEXEL_OFFSET = 7,

 };

 

 const GLenum compressedTextureFormats[] =

diff --git a/src/OpenGL/libGLESv2/Shader.cpp b/src/OpenGL/libGLESv2/Shader.cpp
index 247c88d..63e74e6 100644
--- a/src/OpenGL/libGLESv2/Shader.cpp
+++ b/src/OpenGL/libGLESv2/Shader.cpp
@@ -169,6 +169,10 @@
 	resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
 	resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
 	resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+	resources.MaxVertexOutputVectors = MAX_VERTEX_OUTPUT_VECTORS;

+	resources.MaxFragmentInputVectors = MAX_FRAGMENT_INPUT_VECTORS;

+	resources.MinProgramTexelOffset = MIN_PROGRAM_TEXEL_OFFSET;

+	resources.MaxProgramTexelOffset = MAX_PROGRAM_TEXEL_OFFSET;
 	resources.OES_standard_derivatives = 1;
 	resources.OES_fragment_precision_high = 1;
 	resources.OES_EGL_image_external = 1;
diff --git a/src/Renderer/Context.cpp b/src/Renderer/Context.cpp
index b8f9308..708ad5a 100644
--- a/src/Renderer/Context.cpp
+++ b/src/Renderer/Context.cpp
@@ -291,6 +291,8 @@
 		pixelShader = 0;
 		vertexShader = 0;
 
+		instanceID = 0;
+
 		occlusionEnabled = false;
 
 		pointSpriteEnable = false;
diff --git a/src/Renderer/Context.hpp b/src/Renderer/Context.hpp
index eecd64c..77b71c8 100644
--- a/src/Renderer/Context.hpp
+++ b/src/Renderer/Context.hpp
@@ -443,6 +443,9 @@
 		// Global mipmap bias

 		float bias;

 

+		// Instancing

+		int instanceID;

+

 		// Fixed-function vertex pipeline state

 		bool lightingEnable;

 		bool specularEnable;

diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp
index e4e8e71..6049877 100644
--- a/src/Renderer/Renderer.hpp
+++ b/src/Renderer/Renderer.hpp
@@ -110,6 +110,8 @@
 
 		PS ps;
 
+		int instanceID;
+
 		VertexProcessor::PointSprite point;
 		float lineWidth;
 
diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp
index b4500a5..d5a394c 100644
--- a/src/Renderer/VertexProcessor.cpp
+++ b/src/Renderer/VertexProcessor.cpp
@@ -297,6 +297,11 @@
 		context->vertexFogMode = fogMode;
 	}
 
+	void VertexProcessor::setInstanceID(int instanceID)
+	{
+		context->instanceID = instanceID;
+	}
+
 	void VertexProcessor::setColorVertexEnable(bool colorVertexEnable)
 	{
 		context->setColorVertexEnable(colorVertexEnable);
diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp
index 04d7ade..b10b7a0 100644
--- a/src/Renderer/VertexProcessor.hpp
+++ b/src/Renderer/VertexProcessor.hpp
@@ -205,6 +205,8 @@
 		virtual void setLightAttenuation(unsigned int light, float constant, float linear, float quadratic);

 		virtual void setLightRange(unsigned int light, float lightRange);

 

+		virtual void setInstanceID(int instanceID);

+

 		virtual void setFogEnable(bool fogEnable);

 		virtual void setVertexFogMode(FogMode fogMode);

 		virtual void setRangeFogEnable(bool enable);

diff --git a/src/Shader/VertexShader.cpp b/src/Shader/VertexShader.cpp
index c7e758d..3b888d7 100644
--- a/src/Shader/VertexShader.cpp
+++ b/src/Shader/VertexShader.cpp
@@ -23,6 +23,7 @@
 		version = 0x0300;
 		positionRegister = Pos;
 		pointSizeRegister = -1;   // No vertex point size
+		instanceIdDeclared = false;
 
 		for(int i = 0; i < MAX_INPUT_ATTRIBUTES; i++)
 		{
@@ -53,6 +54,7 @@
 
 		positionRegister = Pos;
 		pointSizeRegister = -1;   // No vertex point size
+		instanceIdDeclared = false;
 
 		for(int i = 0; i < MAX_INPUT_ATTRIBUTES; i++)
 		{
diff --git a/src/Shader/VertexShader.hpp b/src/Shader/VertexShader.hpp
index 3d292c0..3d8f3fe 100644
--- a/src/Shader/VertexShader.hpp
+++ b/src/Shader/VertexShader.hpp
@@ -32,6 +32,8 @@
 		int positionRegister;     // FIXME: Private
 		int pointSizeRegister;    // FIXME: Private
 
+		bool instanceIdDeclared;
+
 		enum {MAX_INPUT_ATTRIBUTES = 16};
 		Semantic input[MAX_INPUT_ATTRIBUTES];       // FIXME: Private