Create the HLSL shadow texture function.

TRAC #23394
Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Nicolas Capens
diff --git a/src/compiler/BaseTypes.h b/src/compiler/BaseTypes.h
index 5654688..2c9fb9e 100644
--- a/src/compiler/BaseTypes.h
+++ b/src/compiler/BaseTypes.h
@@ -254,6 +254,36 @@
     return false;
 }
 
+inline bool IsShadowSampler(TBasicType type)
+{
+    switch (type)
+    {
+      case EbtSampler2DShadow:
+      case EbtSamplerCubeShadow:
+      case EbtSampler2DArrayShadow:
+        return true;
+      case EbtISampler2D:
+      case EbtISampler3D:
+      case EbtISamplerCube:
+      case EbtISampler2DArray:
+      case EbtUSampler2D:
+      case EbtUSampler3D:
+      case EbtUSamplerCube:
+      case EbtUSampler2DArray:
+      case EbtSampler2D:
+      case EbtSampler3D:
+      case EbtSamplerCube:
+      case EbtSamplerExternalOES:
+      case EbtSampler2DRect:
+      case EbtSampler2DArray:
+        return false;
+      default:
+        assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
 //
 // Qualifiers and built-ins.  These are mainly used to see what can be read
 // or written, and by the machine dependent translator to know which registers
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 9ac5ed4..24ff76e 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -554,7 +554,7 @@
         {
             int index = samplerRegister(mReferencedUniforms[name]);
 
-            uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + 
+            uniforms += "uniform " + samplerString(type) + " sampler_" + decorateUniform(name, type) + arrayString(type) + 
                         " : register(s" + str(index) + ");\n";
 
             uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
@@ -888,18 +888,21 @@
         {
             switch(textureFunction->sampler)
             {
-              case EbtSampler2D:       out << "int2 "; break;
-              case EbtSampler3D:       out << "int3 "; break;
-              case EbtSamplerCube:     out << "int2 "; break;
-              case EbtSampler2DArray:  out << "int3 "; break;
-              case EbtISampler2D:      out << "int2 "; break;
-              case EbtISampler3D:      out << "int3 "; break;
-              case EbtISamplerCube:    out << "int2 "; break;
-              case EbtISampler2DArray: out << "int3 "; break;
-              case EbtUSampler2D:      out << "int2 "; break;
-              case EbtUSampler3D:      out << "int3 "; break;
-              case EbtUSamplerCube:    out << "int2 "; break;
-              case EbtUSampler2DArray: out << "int3 "; break;
+              case EbtSampler2D:            out << "int2 "; break;
+              case EbtSampler3D:            out << "int3 "; break;
+              case EbtSamplerCube:          out << "int2 "; break;
+              case EbtSampler2DArray:       out << "int3 "; break;
+              case EbtISampler2D:           out << "int2 "; break;
+              case EbtISampler3D:           out << "int3 "; break;
+              case EbtISamplerCube:         out << "int2 "; break;
+              case EbtISampler2DArray:      out << "int3 "; break;
+              case EbtUSampler2D:           out << "int2 "; break;
+              case EbtUSampler3D:           out << "int3 "; break;
+              case EbtUSamplerCube:         out << "int2 "; break;
+              case EbtUSampler2DArray:      out << "int3 "; break;
+              case EbtSampler2DShadow:      out << "int2 "; break;
+              case EbtSamplerCubeShadow:    out << "int2 "; break;
+              case EbtSampler2DArrayShadow: out << "int3 "; break;
               default: UNREACHABLE();
             }
         }
@@ -907,18 +910,21 @@
         {
             switch(textureFunction->sampler)
             {
-              case EbtSampler2D:       out << "float4 "; break;
-              case EbtSampler3D:       out << "float4 "; break;
-              case EbtSamplerCube:     out << "float4 "; break;
-              case EbtSampler2DArray:  out << "float4 "; break;
-              case EbtISampler2D:      out << "int4 ";   break;
-              case EbtISampler3D:      out << "int4 ";   break;
-              case EbtISamplerCube:    out << "int4 ";   break;
-              case EbtISampler2DArray: out << "int4 ";   break;
-              case EbtUSampler2D:      out << "uint4 ";  break;
-              case EbtUSampler3D:      out << "uint4 ";  break;
-              case EbtUSamplerCube:    out << "uint4 ";  break;
-              case EbtUSampler2DArray: out << "uint4 ";  break;
+              case EbtSampler2D:            out << "float4 "; break;
+              case EbtSampler3D:            out << "float4 "; break;
+              case EbtSamplerCube:          out << "float4 "; break;
+              case EbtSampler2DArray:       out << "float4 "; break;
+              case EbtISampler2D:           out << "int4 ";   break;
+              case EbtISampler3D:           out << "int4 ";   break;
+              case EbtISamplerCube:         out << "int4 ";   break;
+              case EbtISampler2DArray:      out << "int4 ";   break;
+              case EbtUSampler2D:           out << "uint4 ";  break;
+              case EbtUSampler3D:           out << "uint4 ";  break;
+              case EbtUSamplerCube:         out << "uint4 ";  break;
+              case EbtUSampler2DArray:      out << "uint4 ";  break;
+              case EbtSampler2DShadow:      out << "float ";  break;
+              case EbtSamplerCubeShadow:    out << "float ";  break;
+              case EbtSampler2DArrayShadow: out << "float ";  break;
               default: UNREACHABLE();
             }
         }
@@ -951,18 +957,21 @@
         {
             switch(textureFunction->sampler)
             {
-              case EbtSampler2D:       out << "Texture2D x, SamplerState s";             hlslCoords = 2; break;
-              case EbtSampler3D:       out << "Texture3D x, SamplerState s";             hlslCoords = 3; break;
-              case EbtSamplerCube:     out << "TextureCube x, SamplerState s";           hlslCoords = 3; break;
-              case EbtSampler2DArray:  out << "Texture2DArray x, SamplerState s";        hlslCoords = 3; break;
-              case EbtISampler2D:      out << "Texture2D<int4> x, SamplerState s";       hlslCoords = 2; break;
-              case EbtISampler3D:      out << "Texture3D<int4> x, SamplerState s";       hlslCoords = 3; break;
-              case EbtISamplerCube:    out << "TextureCube<int4> x, SamplerState s";     hlslCoords = 3; break;
-              case EbtISampler2DArray: out << "Texture2DArray<int4> x, SamplerState s";  hlslCoords = 3; break;
-              case EbtUSampler2D:      out << "Texture2D<uint4> x, SamplerState s";      hlslCoords = 2; break;
-              case EbtUSampler3D:      out << "Texture3D<uint4> x, SamplerState s";      hlslCoords = 3; break;
-              case EbtUSamplerCube:    out << "TextureCube<uint4> x, SamplerState s";    hlslCoords = 3; break;
-              case EbtUSampler2DArray: out << "Texture2DArray<uint4> x, SamplerState s"; hlslCoords = 3; break;
+              case EbtSampler2D:            out << "Texture2D x, SamplerState s";                hlslCoords = 2; break;
+              case EbtSampler3D:            out << "Texture3D x, SamplerState s";                hlslCoords = 3; break;
+              case EbtSamplerCube:          out << "TextureCube x, SamplerState s";              hlslCoords = 3; break;
+              case EbtSampler2DArray:       out << "Texture2DArray x, SamplerState s";           hlslCoords = 3; break;
+              case EbtISampler2D:           out << "Texture2D<int4> x, SamplerState s";          hlslCoords = 2; break;
+              case EbtISampler3D:           out << "Texture3D<int4> x, SamplerState s";          hlslCoords = 3; break;
+              case EbtISamplerCube:         out << "TextureCube<int4> x, SamplerState s";        hlslCoords = 3; break;
+              case EbtISampler2DArray:      out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
+              case EbtUSampler2D:           out << "Texture2D<uint4> x, SamplerState s";         hlslCoords = 2; break;
+              case EbtUSampler3D:           out << "Texture3D<uint4> x, SamplerState s";         hlslCoords = 3; break;
+              case EbtUSamplerCube:         out << "TextureCube<uint4> x, SamplerState s";       hlslCoords = 3; break;
+              case EbtUSampler2DArray:      out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
+              case EbtSampler2DShadow:      out << "Texture2D x, SamplerComparisonState s";      hlslCoords = 2; break;
+              case EbtSamplerCubeShadow:    out << "TextureCube x, SamplerComparisonState s";    hlslCoords = 3; break;
+              case EbtSampler2DArrayShadow: out << "Texture2DArray x, SamplerComparisonState s"; hlslCoords = 3; break;
               default: UNREACHABLE();
             }
         }
@@ -1014,18 +1023,21 @@
 
             switch(textureFunction->sampler)
             {
-              case EbtSampler2D:       out << "    return int2(width, height);";         break;
-              case EbtSampler3D:       out << "    return int3(width, height, depth);";  break;
-              case EbtSamplerCube:     out << "    return int2(width, height);";         break;
-              case EbtSampler2DArray:  out << "    return int3(width, height, layers);"; break;
-              case EbtISampler2D:      out << "    return int2(width, height);";         break;
-              case EbtISampler3D:      out << "    return int3(width, height, depth);";  break;
-              case EbtISamplerCube:    out << "    return int2(width, height);";         break;
-              case EbtISampler2DArray: out << "    return int3(width, height, layers);"; break;
-              case EbtUSampler2D:      out << "    return int2(width, height);";         break;
-              case EbtUSampler3D:      out << "    return int3(width, height, depth);";  break;
-              case EbtUSamplerCube:    out << "    return int2(width, height);";         break;
-              case EbtUSampler2DArray: out << "    return int3(width, height, layers);"; break;
+              case EbtSampler2D:            out << "    return int2(width, height);";         break;
+              case EbtSampler3D:            out << "    return int3(width, height, depth);";  break;
+              case EbtSamplerCube:          out << "    return int2(width, height);";         break;
+              case EbtSampler2DArray:       out << "    return int3(width, height, layers);"; break;
+              case EbtISampler2D:           out << "    return int2(width, height);";         break;
+              case EbtISampler3D:           out << "    return int3(width, height, depth);";  break;
+              case EbtISamplerCube:         out << "    return int2(width, height);";         break;
+              case EbtISampler2DArray:      out << "    return int3(width, height, layers);"; break;
+              case EbtUSampler2D:           out << "    return int2(width, height);";         break;
+              case EbtUSampler3D:           out << "    return int3(width, height, depth);";  break;
+              case EbtUSamplerCube:         out << "    return int2(width, height);";         break;
+              case EbtUSampler2DArray:      out << "    return int3(width, height, layers);"; break;
+              case EbtSampler2DShadow:      out << "    return int2(width, height);";         break;
+              case EbtSamplerCubeShadow:    out << "    return int2(width, height);";         break;
+              case EbtSampler2DArrayShadow: out << "    return int3(width, height, layers);"; break;
               default: UNREACHABLE();
             }
         }
@@ -1095,6 +1107,10 @@
                 {
                     out << "x.Load(";
                 }
+                else if (IsShadowSampler(textureFunction->sampler))
+                {
+                    out << "x.SampleCmp(s, ";
+                }
                 else
                 {
                     switch(textureFunction->method)
@@ -1197,7 +1213,21 @@
                     out << ", " + addressz + ("t.z" + proj) + close;
                 }
 
-                if (!IsIntegerSampler(textureFunction->sampler))
+                if (IsIntegerSampler(textureFunction->sampler))
+                {
+                    out << ", 0));";   // Sample from the top level
+                }
+                else if (IsShadowSampler(textureFunction->sampler))
+                {
+                    // Compare value
+                    switch(textureFunction->coords)
+                    {
+                      case 3: out << "), t.z);"; break;
+                      case 4: out << "), t.w);"; break;
+                      default: UNREACHABLE();
+                    }
+                }
+                else
                 {
                     switch(textureFunction->method)
                     {
@@ -1208,10 +1238,6 @@
                       default: UNREACHABLE();
                     }
                 }
-                else
-                {
-                    out << ", 0));";   // Sample from the top level
-                }
             }
             else UNREACHABLE();
         }
@@ -3021,8 +3047,8 @@
 
     if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
     {
-       return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
-              qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type);
+        return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
+               qualifierString(qualifier) + " " + samplerString(type) + " sampler_" + name + arrayString(type);        
     }
 
     return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
@@ -3147,27 +3173,40 @@
 {
     switch (type.getBasicType())
     {
-      case EbtSampler2D:          return "Texture2D";
-      case EbtSamplerCube:        return "TextureCube";
-      case EbtSamplerExternalOES: return "Texture2D";
-      case EbtSampler2DArray:     return "Texture2DArray";
-      case EbtSampler3D:          return "Texture3D";
-      case EbtISampler2D:         return "Texture2D<int4>";
-      case EbtISampler3D:         return "Texture3D<int4>";
-      case EbtISamplerCube:       return "TextureCube<int4>";
-      case EbtISampler2DArray:    return "Texture2DArray<int4>";
-      case EbtUSampler2D:         return "Texture2D<uint4>";
-      case EbtUSampler3D:         return "Texture3D<uint4>";
-      case EbtUSamplerCube:       return "TextureCube<uint4>";
-      case EbtUSampler2DArray:    return "Texture2DArray<uint4>";
-      default:
-        break;
+      case EbtSampler2D:            return "Texture2D";
+      case EbtSamplerCube:          return "TextureCube";
+      case EbtSamplerExternalOES:   return "Texture2D";
+      case EbtSampler2DArray:       return "Texture2DArray";
+      case EbtSampler3D:            return "Texture3D";
+      case EbtISampler2D:           return "Texture2D<int4>";
+      case EbtISampler3D:           return "Texture3D<int4>";
+      case EbtISamplerCube:         return "TextureCube<int4>";
+      case EbtISampler2DArray:      return "Texture2DArray<int4>";
+      case EbtUSampler2D:           return "Texture2D<uint4>";
+      case EbtUSampler3D:           return "Texture3D<uint4>";
+      case EbtUSamplerCube:         return "TextureCube<uint4>";
+      case EbtUSampler2DArray:      return "Texture2DArray<uint4>";
+      case EbtSampler2DShadow:      return "Texture2D";
+      case EbtSamplerCubeShadow:    return "TextureCube";
+      case EbtSampler2DArrayShadow: return "Texture2DArray";
+      default: UNREACHABLE();
     }
-
-    UNREACHABLE();
+    
     return "<unknown texture type>";
 }
 
+TString OutputHLSL::samplerString(const TType &type)
+{
+    if (IsShadowSampler(type.getBasicType()))
+    {
+        return "SamplerComparisonState";
+    }
+    else
+    {
+        return "SamplerState";
+    }
+}
+
 TString OutputHLSL::arrayString(const TType &type)
 {
     if (!type.isArray())
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index 2a3736c..73409e8 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -39,6 +39,7 @@
 
     TString typeString(const TType &type);
     TString textureString(const TType &type);
+    TString samplerString(const TType &type);
     TString interpolationString(TQualifier qualifier);
     TString structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);
     TString structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);