Fix deterministic loops within conditional blocks, again.

Deterministic loops use the first scalar of the SIMD register used as
the loop index, for addressing arrays. This means that operations on the
index register should not be masked (i.e. it should be treated as a
scalar).

Previously we were still masking it based on conditional statements, and
we didn't disable the masking altogether for the loop initialization and
initial test. A new shader assembly instruction 'SCALAR' was added for
doing this.

Previously this was conflated with the 'TEST' instruction, which should
independently disable/restore the 'continue' mask.

Bug swiftshader:93
Bug b/118009174

Change-Id: I4add1a6d74231f463217e57adfabdc81faf489ae
Reviewed-on: https://swiftshader-review.googlesource.com/c/22348
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index d492c65..55cc8c8 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -26,10 +26,6 @@
 	VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
 		: VertexRoutine(state, shader), shader(shader), r(shader->indirectAddressableTemporaries)
 	{
-		ifDepth = 0;
-		loopRepDepth = 0;
-		currentLabel = -1;
-
 		for(int i = 0; i < 2048; i++)
 		{
 			labelBlock[i] = 0;
@@ -295,6 +291,7 @@
 			case Shader::OPCODE_BREAKP:     BREAKP(src0);                   break;
 			case Shader::OPCODE_CONTINUE:   CONTINUE();                     break;
 			case Shader::OPCODE_TEST:       TEST();                         break;
+			case Shader::OPCODE_SCALAR:     SCALAR();                       break;
 			case Shader::OPCODE_CALL:       CALL(dst.label, dst.callSite);  break;
 			case Shader::OPCODE_CALLNZ:     CALLNZ(dst.label, dst.callSite, src0); break;
 			case Shader::OPCODE_ELSE:       ELSE();                         break;
@@ -977,6 +974,11 @@
 
 	Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
 	{
+		if(scalar)
+		{
+			return Int4(0xFFFFFFFF);
+		}
+
 		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
 
 		if(shader->containsBreakInstruction() && instruction->analysisBreak)
@@ -1108,6 +1110,11 @@
 		restoreContinue.pop_back();
 	}
 
+	void VertexProgram::SCALAR()
+	{
+		scalar = true;
+	}
+
 	void VertexProgram::CALL(int labelIndex, int callSiteIndex)
 	{
 		if(!labelBlock[labelIndex])
@@ -1284,6 +1291,7 @@
 		Nucleus::setInsertBlock(endBlock);
 
 		enableIndex--;
+		scalar = false;
 	}
 
 	void VertexProgram::ENDSWITCH()
@@ -1490,6 +1498,7 @@
 		Nucleus::setInsertBlock(loopBlock);
 
 		loopRepDepth++;
+		scalar = false;
 	}
 
 	void VertexProgram::SWITCH()