Implement dynamic indexing of temporaries.

Previously only dynamic indexing of uniforms was supported.

Since this is essentially a gather operation within the register file,
it is slow. We optimize the common case of using the loop index
variable as relative address, where the index value would be the same
for all shader invocations running in lock-step across SIMD lanes.

Bug chromium:845103
Bug skia:7846

Change-Id: Idb36b512dd560d740ac9088691b633ff3a1561c1
Reviewed-on: https://swiftshader-review.googlesource.com/18968
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index cbfbf56..d7213cb 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -1831,6 +1831,11 @@
 			return false;
 		}
 
+		if(loop.isDeterministic())
+		{
+			 deterministicVariables.insert(loop.index->getId());
+		}
+
 		bool unroll = (loop.iterations <= 4);
 
 		TIntermNode *init = node->getInit();
@@ -1916,6 +1921,11 @@
 			}
 		}
 
+		if(loop.isDeterministic())
+		{
+			 deterministicVariables.erase(loop.index->getId());
+		}
+
 		return false;
 	}
 
@@ -2651,10 +2661,12 @@
 								sw::Shader::SourceParameter relativeRegister;
 								source(relativeRegister, right);
 
+								int indexId = right->getAsSymbolNode() ? right->getAsSymbolNode()->getId() : 0;
+
 								rel.index = relativeRegister.index;
 								rel.type = relativeRegister.type;
 								rel.scale = scale;
-								rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform);
+								rel.dynamic = (right->getQualifier() != EvqUniform) && (deterministicVariables.count(indexId) == 0);
 							}
 						}
 						else if(rel.index != registerIndex(&address))   // Move the previous index register to the address register