Add support to the GLSL to HLSL translator for interface blocks with instance names.

TRAC #22930

Signed-off-by: Nicolas Capens
Signed-off-by: Geoff Lang
Author: Jamie Madill

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2345 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 808c99b..6057e6b 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -156,6 +156,18 @@
     return elementSize * arraySize;
 }
 
+TString OutputHLSL::interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType)
+{
+    if (interfaceBlockType.hasInstanceName())
+    {
+        return interfaceBlockType.getTypeName() + "." + uniformType.getFieldName();
+    }
+    else
+    {
+        return uniformType.getFieldName();
+    }
+}
+
 void OutputHLSL::header()
 {
     ShShaderType shaderType = mContext.shaderType;
@@ -200,7 +212,8 @@
 
     for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
     {
-        const TType &interfaceBlockType = *interfaceBlockIt->second->getType().getInterfaceBlockType();
+        const TType &nodeType = interfaceBlockIt->second->getType();
+        const TType &interfaceBlockType = nodeType.isInterfaceBlockMember() ? *nodeType.getInterfaceBlockType() : nodeType;
         const TString &blockName = interfaceBlockType.getTypeName();
         const TTypeList &typeList = *interfaceBlockType.getStruct();
 
@@ -208,7 +221,8 @@
         for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
         {
             const TType &memberType = *typeList[typeIndex].type;
-            declareUniformToList(memberType, memberType.getFieldName(), typeIndex, interfaceBlock.activeUniforms);
+            const TString &fullUniformName = interfaceBlockUniformName(interfaceBlockType, memberType);
+            declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms);
         }
 
         // TODO: handle other block layouts
@@ -218,6 +232,11 @@
         interfaceBlocks += "cbuffer " + blockName + " : register(b" + str(interfaceBlock.registerIndex) + ")\n"
                            "{\n";
 
+        if (interfaceBlockType.hasInstanceName())
+        {
+            interfaceBlocks += "  struct {\n";
+        }
+
         for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
         {
             // TODO: padding for standard layout
@@ -225,6 +244,11 @@
             interfaceBlocks += "    " + typeString(memberType) + " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
         }
 
+        if (interfaceBlockType.hasInstanceName())
+        {
+            interfaceBlocks += "  } " + decorate(interfaceBlockType.getInstanceName()) + ";\n";
+        }
+
         interfaceBlocks += "};\n\n";
     }
 
@@ -1204,6 +1228,12 @@
                 mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
                 out << decorateUniform(name, node->getType());
             }
+            else if (node->getBasicType() == EbtInterfaceBlock)
+            {
+                const TString& interfaceBlockTypeName = node->getType().getTypeName();
+                mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
+                out << decorateUniform(name, node->getType());
+            }
             else
             {
                 mReferencedUniforms[name] = node;
@@ -1338,6 +1368,7 @@
       case EOpIndexDirect:             outputTriplet(visit, "", "[", "]");              break;
       case EOpIndexIndirect:           outputTriplet(visit, "", "[", "]");              break;
       case EOpIndexDirectStruct:
+      case EOpIndexDirectInterfaceBlock:
         if (visit == InVisit)
         {
             out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());