Manually compute the mipmap size for the textureSize builtin.

There were two issues with the current implementation:
 * The GetDimensions function already takes into account the base level of the
   SRV.
 * The GetDimensions function returns doesn't return valid sizes for levels
   that don't exist in the SRV.  Instead, manually do the lod offset.

BUG=angleproject:931
BUG=angleproject:1316

TEST=dEQP-GLES3.functional.shaders.texture_functions.texturesize.sampler2d_fixed_vertex

Change-Id: I63259b563a42b93b73949e0ef7ac412099a42f13
Reviewed-on: https://chromium-review.googlesource.com/376099
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/compiler/translator/TextureFunctionHLSL.cpp b/src/compiler/translator/TextureFunctionHLSL.cpp
index f0b48d0..6580f25 100644
--- a/src/compiler/translator/TextureFunctionHLSL.cpp
+++ b/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -473,22 +473,40 @@
 
 void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
                                    const TextureFunctionHLSL::TextureFunction &textureFunction,
-                                   const TString &textureReference)
+                                   const TString &textureReference,
+                                   bool getDimensionsIgnoresBaseLevel)
 {
-    out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
+    if (getDimensionsIgnoresBaseLevel)
+    {
+        out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
+    }
+    else
+    {
+        out << "int baseLevel = 0;\n";
+    }
+
     if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
         (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
     {
         // "depth" stores either the number of layers in an array texture or 3D depth
         out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
             << "    " << textureReference
-            << ".GetDimensions(baseLevel + lod, width, height, depth, numberOfLevels);\n";
+            << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
+            << "    width = max(width >> lod, 1);\n"
+            << "    height = max(height >> lod, 1);\n";
+
+        if (!IsSamplerArray(textureFunction.sampler))
+        {
+            out << "    depth = max(depth >> lod, 1);\n";
+        }
     }
     else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
     {
         out << "    uint width; uint height; uint numberOfLevels;\n"
             << "    " << textureReference
-            << ".GetDimensions(baseLevel + lod, width, height, numberOfLevels);\n";
+            << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
+            << "    width = max(width >> lod, 1);\n"
+            << "    height = max(height >> lod, 1);\n";
     }
     else
         UNREACHABLE();
@@ -1249,7 +1267,9 @@
     return textureFunction.name();
 }
 
-void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out, const ShShaderOutput outputType)
+void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out,
+                                                const ShShaderOutput outputType,
+                                                bool getDimensionsIgnoresBaseLevel)
 {
     for (const TextureFunction &textureFunction : mUsesTexture)
     {
@@ -1272,7 +1292,8 @@
 
         if (textureFunction.method == TextureFunction::SIZE)
         {
-            OutputTextureSizeFunctionBody(out, textureFunction, textureReference);
+            OutputTextureSizeFunctionBody(out, textureFunction, textureReference,
+                                          getDimensionsIgnoresBaseLevel);
         }
         else
         {