Proper handling of Interface Block indexing

This is a first step in handling interface blocks
properly by allowing indexing of blocks to be handled
properly. This does not include any interaction with
the Program, which will come in a following step.

No WebGL tests were injured in the making of this cl.

Change-Id: I575b08502f7f4dd63ca7b57f2ca0630367adf0de
Reviewed-on: https://swiftshader-review.googlesource.com/3589
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index 59e1065..d268672 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -322,11 +322,14 @@
 			}

 			break;

 		case EOpIndexDirectStruct:

+		case EOpIndexDirectInterfaceBlock:

 			if(visit == PostVisit)

 			{

-				ASSERT(leftType.isStruct());

+				ASSERT(leftType.isStruct() || (leftType.isInterfaceBlock()));

 

-				const TFieldList& fields = leftType.getStruct()->fields();

+				const TFieldList& fields = (node->getOp() == EOpIndexDirectStruct) ?

+				                           leftType.getStruct()->fields() :

+				                           leftType.getInterfaceBlock()->fields();

 				int index = right->getAsConstantUnion()->getIConst(0);

 				int fieldOffset = 0;

 

@@ -1436,9 +1439,9 @@
 			return index * type.getElementSize() + componentCount(type, registers);

 		}

 

-		if(type.isStruct())

+		if(type.isStruct() || type.isInterfaceBlock())

 		{

-			const TFieldList& fields = type.getStruct()->fields();

+			const TFieldList& fields = type.getStruct() ? type.getStruct()->fields() : type.getInterfaceBlock()->fields();

 			int elements = 0;

 

 			for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++)

@@ -1484,9 +1487,9 @@
 			return registerSize(type, registers);

 		}

 

-		if(type.isStruct())

+		if(type.isStruct() || type.isInterfaceBlock())

 		{

-			const TFieldList& fields = type.getStruct()->fields();

+			const TFieldList& fields = type.getStruct() ? type.getStruct()->fields() : type.getInterfaceBlock()->fields();

 			int elements = 0;

 

 			for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++)

@@ -1559,12 +1562,12 @@
 						TIntermTyped *left = binary->getLeft();

 						TIntermTyped *right = binary->getRight();

 

-						if(binary->getOp() == EOpIndexDirect)

+						switch(binary->getOp())

 						{

+						case EOpIndexDirect:

 							parameter.index += right->getAsConstantUnion()->getIConst(0);

-						}

-						else if(binary->getOp() == EOpIndexIndirect)

-						{

+							break;

+						case EOpIndexIndirect:

 							if(left->getArraySize() > 1)

 							{

 								parameter.rel.type = registerType(binary->getRight());

@@ -1572,12 +1575,14 @@
 								parameter.rel.scale = 1;

 								parameter.rel.deterministic = true;

 							}

-						}

-						else if(binary->getOp() == EOpIndexDirectStruct)

-						{

+							break;

+						case EOpIndexDirectStruct:

+						case EOpIndexDirectInterfaceBlock:

 							parameter.index += right->getAsConstantUnion()->getIConst(0);

+							break;

+						default:

+							UNREACHABLE(binary->getOp());

 						}

-						else UNREACHABLE(binary->getOp());

 					}

 				}

 			}

@@ -1768,8 +1773,11 @@
 				}

 				break;

 			case EOpIndexDirectStruct:

+			case EOpIndexDirectInterfaceBlock:

 				{

-					const TFieldList& fields = left->getType().getStruct()->fields();

+					const TFieldList& fields = (binary->getOp() == EOpIndexDirectStruct) ?

+				                               left->getType().getStruct()->fields() :

+				                               left->getType().getInterfaceBlock()->fields();

 					int index = right->getAsConstantUnion()->getIConst(0);

 					int fieldOffset = 0;

 

@@ -1975,6 +1983,7 @@
 			case EOpVectorSwizzle:

 			case EOpIndexDirect:

 			case EOpIndexDirectStruct:

+			case EOpIndexDirectInterfaceBlock:

 				return cost(binary->getLeft(), budget - 0);

 			case EOpAdd:

 			case EOpSub:

@@ -2156,17 +2165,18 @@
 	{

 		const TType &type = uniform->getType();

 		ASSERT(!IsSampler(type.getBasicType()));

+		TInterfaceBlock *block = type.getAsInterfaceBlock();

 		TIntermSymbol *symbol = uniform->getAsSymbolNode();

-		ASSERT(symbol);

+		ASSERT(symbol || block);

 

-		if(symbol)

+		if(symbol || block)

 		{

 			int index = lookup(uniforms, uniform);

 

 			if(index == -1)

 			{

 				index = allocate(uniforms, uniform);

-				const TString &name = symbol->getSymbol().c_str();

+				const TString &name = symbol ? symbol->getSymbol() : block->name();

 

 				declareUniform(type, name, index);

 			}

@@ -2225,7 +2235,8 @@
 		}

 		else if(binary)

 		{

-			ASSERT(binary->getOp() == EOpIndexDirect || binary->getOp() == EOpIndexIndirect || binary->getOp() == EOpIndexDirectStruct);

+			ASSERT(binary->getOp() == EOpIndexDirect || binary->getOp() == EOpIndexIndirect ||

+				   binary->getOp() == EOpIndexDirectStruct || binary->getOp() == EOpIndexDirectInterfaceBlock);

 

 			return samplerRegister(binary->getLeft());   // Index added later

 		}

@@ -2266,6 +2277,7 @@
 		}

 

 		TIntermSymbol *varSymbol = variable->getAsSymbolNode();

+		TInterfaceBlock *varBlock = variable->getType().getAsInterfaceBlock();

 

 		if(varSymbol)

 		{

@@ -2289,6 +2301,29 @@
 				}

 			}

 		}

+		else if(varBlock)

+		{

+			for(unsigned int i = 0; i < list.size(); i++)

+			{

+				if(list[i])

+				{

+					TInterfaceBlock *listBlock = list[i]->getType().getAsInterfaceBlock();

+

+					if(listBlock)

+					{

+						if(listBlock->name() == varBlock->name())

+						{

+							ASSERT(listBlock->arraySize() == varBlock->arraySize());

+							ASSERT(listBlock->fields() == varBlock->fields());

+							ASSERT(listBlock->blockStorage() == varBlock->blockStorage());

+							ASSERT(listBlock->matrixPacking() == varBlock->matrixPacking());

+

+							return i;

+						}

+					}

+				}

+			}

+		}

 

 		return -1;

 	}

diff --git a/src/OpenGL/compiler/Types.h b/src/OpenGL/compiler/Types.h
index 0457627..cb2722c 100644
--- a/src/OpenGL/compiler/Types.h
+++ b/src/OpenGL/compiler/Types.h
@@ -361,6 +361,7 @@
 	TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; }
 	void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; }
 	bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
+	TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; }
 
 	bool isVector() const { return primarySize > 1 && !isMatrix(); }
 	bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure; }