SPV: Fix issue #159: use ExplicitLod forms for non-fragment stages.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 8150997..ed86cc2 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -2236,6 +2236,7 @@
 
     params.coords = arguments[1];
     int extraArgs = 0;
+    bool noImplicitLod = false;
 
     // sort out where Dref is coming from
     if (cubeCompare) {
@@ -2257,7 +2258,11 @@
     if (cracked.lod) {
         params.lod = arguments[2];
         ++extraArgs;
-    } else if (sampler.ms) {
+    } else if (glslangIntermediate->getStage() != EShLangFragment) {
+        // we need to invent the default lod for an explicit lod instruction for a non-fragment stage
+        noImplicitLod = true;
+    }
+    if (sampler.ms) {
         params.sample = arguments[2]; // For MS, "sample" should be specified
         ++extraArgs;
     }
@@ -2295,7 +2300,7 @@
         }
     }
 
-    return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), sparse, cracked.fetch, cracked.proj, cracked.gather, params);
+    return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params);
 }
 
 spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 10ba32c..2d6e50e 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1286,7 +1286,7 @@
 
 // Accept all parameters needed to create a texture instruction.
 // Create the correct instruction based on the inputs, and make the call.
-Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
+Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicitLod, const TextureParameters& parameters)
 {
     static const int maxTextureArgs = 10;
     Id texArgs[maxTextureArgs] = {};
@@ -1295,7 +1295,7 @@
     // Set up the fixed arguments
     //
     int numArgs = 0;
-    bool xplicit = false;
+    bool explicitLod = false;
     texArgs[numArgs++] = parameters.sampler;
     texArgs[numArgs++] = parameters.coords;
     if (parameters.Dref)
@@ -1316,13 +1316,18 @@
     if (parameters.lod) {
         mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
         texArgs[numArgs++] = parameters.lod;
-        xplicit = true;
-    }
-    if (parameters.gradX) {
+        explicitLod = true;
+    } else if (parameters.gradX) {
         mask = (ImageOperandsMask)(mask | ImageOperandsGradMask);
         texArgs[numArgs++] = parameters.gradX;
         texArgs[numArgs++] = parameters.gradY;
-        xplicit = true;
+        explicitLod = true;
+    } else if (noImplicitLod && ! fetch && ! gather) {
+        // have to explicitly use lod of 0 if not allowed to have them be implicit, and
+        // we would otherwise be about to issue an implicit instruction
+        mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
+        texArgs[numArgs++] = makeFloatConstant(0.0);
+        explicitLod = true;
     }
     if (parameters.offset) {
         if (isConstant(parameters.offset))
@@ -1354,8 +1359,7 @@
     //
     // Set up the instruction
     //
-    Op opCode;
-    opCode = OpImageSampleImplicitLod;
+    Op opCode = OpNop;  // All paths below need to set this
     if (fetch) {
         if (sparse)
             opCode = OpImageSparseFetch;
@@ -1372,7 +1376,7 @@
                 opCode = OpImageSparseGather;
             else
                 opCode = OpImageGather;
-    } else if (xplicit) {
+    } else if (explicitLod) {
         if (parameters.Dref) {
             if (proj)
                 if (sparse)
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 074f8d2..b2daffb 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -323,7 +323,7 @@
     };
 
     // Select the correct texture operation based on all inputs, and emit the correct instruction
-    Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters&);
+    Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicit, const TextureParameters&);
 
     // Emit the OpTextureQuery* instruction that was passed in.
     // Figure out the right return value and type, and return it.
diff --git a/Test/baseResults/spv.150.vert.out b/Test/baseResults/spv.150.vert.out
index 2a347b4..3e86aec 100755
--- a/Test/baseResults/spv.150.vert.out
+++ b/Test/baseResults/spv.150.vert.out
@@ -5,13 +5,13 @@
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 50
+// Id's are bound by 67
 
                               Capability Shader
                               Capability ClipDistance
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Vertex 4  "main" 13 17 39 48 49
+                              EntryPoint Vertex 4  "main" 13 17 39 65 66
                               Source GLSL 150
                               Name 4  "main"
                               Name 11  "gl_PerVertex"
@@ -30,16 +30,17 @@
                               MemberName 37(s2) 1  "d"
                               Name 39  "s2out"
                               Name 41  "i"
-                              Name 46  "ui"
-                              Name 48  "gl_VertexID"
-                              Name 49  "gl_InstanceID"
+                              Name 48  "s2D"
+                              Name 63  "ui"
+                              Name 65  "gl_VertexID"
+                              Name 66  "gl_InstanceID"
                               MemberDecorate 11(gl_PerVertex) 0 Invariant
                               MemberDecorate 11(gl_PerVertex) 0 BuiltIn Position
                               MemberDecorate 11(gl_PerVertex) 1 BuiltIn PointSize
                               MemberDecorate 11(gl_PerVertex) 2 BuiltIn ClipDistance
                               Decorate 11(gl_PerVertex) Block
-                              Decorate 48(gl_VertexID) BuiltIn VertexId
-                              Decorate 49(gl_InstanceID) BuiltIn InstanceId
+                              Decorate 65(gl_VertexID) BuiltIn VertexId
+                              Decorate 66(gl_InstanceID) BuiltIn InstanceId
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
@@ -70,11 +71,22 @@
               38:             TypePointer Output 37(s2)
        39(s2out):     38(ptr) Variable Output
               40:             TypePointer Function 14(int)
-              45:             TypePointer UniformConstant 14(int)
-          46(ui):     45(ptr) Variable UniformConstant
-              47:             TypePointer Input 14(int)
- 48(gl_VertexID):     47(ptr) Variable Input
-49(gl_InstanceID):     47(ptr) Variable Input
+              45:             TypeImage 6(float) 2D sampled format:Unknown
+              46:             TypeSampledImage 45
+              47:             TypePointer UniformConstant 46
+         48(s2D):     47(ptr) Variable UniformConstant
+              50:             TypeVector 6(float) 2
+              51:    6(float) Constant 1056964608
+              52:   50(fvec2) ConstantComposite 51 51
+              53:    6(float) Constant 0
+              56:             TypeVector 6(float) 3
+              57:   56(fvec3) ConstantComposite 51 51 51
+              60:    6(float) Constant 1078774989
+              62:             TypePointer UniformConstant 14(int)
+          63(ui):     62(ptr) Variable UniformConstant
+              64:             TypePointer Input 14(int)
+ 65(gl_VertexID):     64(ptr) Variable Input
+66(gl_InstanceID):     64(ptr) Variable Input
          4(main):           2 Function None 3
                5:             Label
            41(i):     40(ptr) Variable Function
@@ -92,5 +104,11 @@
               43:    6(float) Load 23(ps)
               44:     25(ptr) AccessChain 39(s2out) 21 42 27 27 33
                               Store 44 43
+              49:          46 Load 48(s2D)
+              54:    7(fvec4) ImageSampleExplicitLod 49 52 Lod 53
+              55:          46 Load 48(s2D)
+              58:    7(fvec4) ImageSampleProjExplicitLod 55 57 Lod 53
+              59:          46 Load 48(s2D)
+              61:    7(fvec4) ImageSampleExplicitLod 59 52 Lod 60
                               Return
                               FunctionEnd
diff --git a/Test/spv.150.vert b/Test/spv.150.vert
index 065275f..686b14b 100644
--- a/Test/spv.150.vert
+++ b/Test/spv.150.vert
@@ -4,6 +4,7 @@
 

 uniform float ps;

 uniform int ui;

+uniform sampler2D s2D;

 

 invariant gl_Position;

 

@@ -27,13 +28,11 @@
     gl_ClipDistance[2] = iv4.x;

     int i;

     s2out.d[i].b[2].w = ps;

-    

-    // test recovery from nonsupported built-ins    

-    //float n1 = noise1(2.4);

-    //n1 = noise1(vec4(n1));

-    //vec2 n2 = noise2(vec3(n1));

-    //vec3 n3 = noise3(n2);

-    //vec4 n4 = noise4(n3);

+

+    // test non-implicit lod

+    texture(s2D, vec2(0.5));

+    textureProj(s2D, vec3(0.5));

+    textureLod(s2D, vec2(0.5), 3.2);

 }

 

 out float gl_ClipDistance[4];