Implement mipmapping for integer samplers.

TRAC #23655
Signed-off-by: Geoff Lang
Signed-off-by: Shannon Woods
Author: Nicolas Capens
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index b1c3888..15cce63 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -1043,19 +1043,94 @@
                 {
                     if (IsSamplerArray(textureFunction->sampler))
                     {
-                        out << "    float width; float height; float layers;\n"
-                               "    x.GetDimensions(width, height, layers);\n";
+                        out << "    float width; float height; float layers; float levels;\n";
+                            
+                        if (textureFunction->method == TextureFunction::LOD0)
+                        {
+                            out << "    uint mip = 0;\n";
+                        }
+                        else
+                        {
+                            if (textureFunction->method == TextureFunction::IMPLICIT ||
+                                textureFunction->method == TextureFunction::BIAS)
+                            {
+                                out << "    x.GetDimensions(0, width, height, layers, levels);\n"
+                                       "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                                       "    float dx = length(ddx(tSized));\n"
+                                       "    float dy = length(ddy(tSized));\n"
+                                       "    float lod = log2(max(sqrt(dx), sqrt(dy)));\n";
+
+                                if (textureFunction->method == TextureFunction::BIAS)
+                                {
+                                    out << "    lod += bias;\n";
+                                }
+                            }
+
+                            out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+                        }
+
+                        out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
                     }
                     else
                     {
-                        out << "    float width; float height;\n"
-                               "    x.GetDimensions(width, height);\n";
+                        out << "    float width; float height; float levels;\n";
+                             
+                        if (textureFunction->method == TextureFunction::LOD0)
+                        {
+                            out << "    uint mip = 0;\n";
+                        }
+                        else
+                        {
+                            if (textureFunction->method == TextureFunction::IMPLICIT ||
+                                textureFunction->method == TextureFunction::BIAS)
+                            {
+                                out << "    x.GetDimensions(0, width, height, levels);\n"
+                                       "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                                       "    float dx = length(ddx(tSized));\n"
+                                       "    float dy = length(ddy(tSized));\n"
+                                       "    float lod = log2(max(sqrt(dx), sqrt(dy)));\n";
+
+                                if (textureFunction->method == TextureFunction::BIAS)
+                                {
+                                    out << "    lod += bias;\n";
+                                }
+                            }
+
+                            out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+                        }
+
+                        out << "    x.GetDimensions(mip, width, height, levels);\n";
                     }
                 }
                 else if (IsSampler3D(textureFunction->sampler))
                 {
-                    out << "    float width; float height; float depth;\n"
-                           "    x.GetDimensions(width, height, depth);\n";
+                    out << "    float width; float height; float depth; float levels;\n";
+                      
+                    if (textureFunction->method == TextureFunction::LOD0)
+                    {
+                        out << "    uint mip = 0;\n";
+                    }
+                    else
+                    {
+                        if (textureFunction->method == TextureFunction::IMPLICIT ||
+                            textureFunction->method == TextureFunction::BIAS)
+                        {
+                            out << "    x.GetDimensions(0, width, height, depth, levels);\n"
+                                   "    float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n"
+                                   "    float dx = length(ddx(tSized));\n"
+                                   "    float dy = length(ddy(tSized));\n"
+                                   "    float lod = log2(max(sqrt(dx), sqrt(dy)));\n";
+
+                            if (textureFunction->method == TextureFunction::BIAS)
+                            {
+                                out << "    lod += bias;\n";
+                            }
+                        }
+
+                        out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+                    }
+
+                    out << "    x.GetDimensions(mip, width, height, depth, levels);\n";
                 }
                 else UNREACHABLE();
             }
@@ -1195,7 +1270,7 @@
 
                 if (IsIntegerSampler(textureFunction->sampler))
                 {
-                    out << ", 0));";   // Sample from the top level
+                    out << ", mip));";
                 }
                 else if (IsShadowSampler(textureFunction->sampler))
                 {