Merge pull request #849 from steve-lunarg/samplercmp-errmsg

HLSL: add error for expected comparison sampler in SampleCmp* ops
diff --git a/Test/baseResults/hlsl.samplecmp.negative.frag.out b/Test/baseResults/hlsl.samplecmp.negative.frag.out
new file mode 100644
index 0000000..99cfdbf
--- /dev/null
+++ b/Test/baseResults/hlsl.samplecmp.negative.frag.out
@@ -0,0 +1,96 @@
+hlsl.samplecmp.negative.frag
+ERROR: 0:9: '' : expected: SamplerComparisonState 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:7  Function Definition: @main( ( temp 4-component vector of float)
+0:7    Function Parameters: 
+0:?     Sequence
+0:8      texture ( temp float)
+0:8        Construct combined texture-sampler ( temp sampler2DShadow)
+0:8          'g_shadowTex' ( uniform texture2D)
+0:8          'g_shadowSamplerComp' ( uniform sampler)
+0:8        Construct vec3 ( temp 3-component vector of float)
+0:?           Constant:
+0:?             0.000000
+0:?             0.000000
+0:8          Constant:
+0:8            0.000000
+0:9      ERROR: Bad aggregation op
+ ( temp float)
+0:9        'g_shadowTex' ( uniform texture2D)
+0:9        'g_shadowSampler' ( uniform sampler)
+0:?         Constant:
+0:?           0.000000
+0:?           0.000000
+0:9        Constant:
+0:9          0.000000
+0:11      Branch: Return with expression
+0:11        Constant:
+0:11          0.000000
+0:11          0.000000
+0:11          0.000000
+0:11          0.000000
+0:7  Function Definition: main( ( temp void)
+0:7    Function Parameters: 
+0:?     Sequence
+0:7      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:7        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_shadowTex' ( uniform texture2D)
+0:?     'g_shadowSampler' ( uniform sampler)
+0:?     'g_shadowSamplerComp' ( uniform sampler)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:7  Function Definition: @main( ( temp 4-component vector of float)
+0:7    Function Parameters: 
+0:?     Sequence
+0:8      texture ( temp float)
+0:8        Construct combined texture-sampler ( temp sampler2DShadow)
+0:8          'g_shadowTex' ( uniform texture2D)
+0:8          'g_shadowSamplerComp' ( uniform sampler)
+0:8        Construct vec3 ( temp 3-component vector of float)
+0:?           Constant:
+0:?             0.000000
+0:?             0.000000
+0:8          Constant:
+0:8            0.000000
+0:9      ERROR: Bad aggregation op
+ ( temp float)
+0:9        'g_shadowTex' ( uniform texture2D)
+0:9        'g_shadowSampler' ( uniform sampler)
+0:?         Constant:
+0:?           0.000000
+0:?           0.000000
+0:9        Constant:
+0:9          0.000000
+0:11      Branch: Return with expression
+0:11        Constant:
+0:11          0.000000
+0:11          0.000000
+0:11          0.000000
+0:11          0.000000
+0:7  Function Definition: main( ( temp void)
+0:7    Function Parameters: 
+0:?     Sequence
+0:7      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:7        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_shadowTex' ( uniform texture2D)
+0:?     'g_shadowSampler' ( uniform sampler)
+0:?     'g_shadowSamplerComp' ( uniform sampler)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+SPIR-V is not generated for failed compile or link
diff --git a/Test/baseResults/hlsl.samplecmp.negative2.frag.out b/Test/baseResults/hlsl.samplecmp.negative2.frag.out
new file mode 100644
index 0000000..996b3f8
--- /dev/null
+++ b/Test/baseResults/hlsl.samplecmp.negative2.frag.out
@@ -0,0 +1,80 @@
+hlsl.samplecmp.negative2.frag
+ERROR: 0:7: '' : expected: SamplerComparisonState 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:6  Function Definition: @main( ( temp 4-component vector of float)
+0:6    Function Parameters: 
+0:?     Sequence
+0:7      ERROR: Bad aggregation op
+ ( temp 4-component vector of float)
+0:7        'g_shadowTex' ( uniform texture2D)
+0:7        'g_shadowSampler' ( uniform sampler)
+0:?         Constant:
+0:?           0.000000
+0:?           0.000000
+0:7        Constant:
+0:7          0.000000
+0:?         Constant:
+0:?           0 (const int)
+0:?           0 (const int)
+0:9      Branch: Return with expression
+0:9        Constant:
+0:9          0.000000
+0:9          0.000000
+0:9          0.000000
+0:9          0.000000
+0:6  Function Definition: main( ( temp void)
+0:6    Function Parameters: 
+0:?     Sequence
+0:6      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:6        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_shadowTex' ( uniform texture2D)
+0:?     'g_shadowSampler' ( uniform sampler)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:6  Function Definition: @main( ( temp 4-component vector of float)
+0:6    Function Parameters: 
+0:?     Sequence
+0:7      ERROR: Bad aggregation op
+ ( temp 4-component vector of float)
+0:7        'g_shadowTex' ( uniform texture2D)
+0:7        'g_shadowSampler' ( uniform sampler)
+0:?         Constant:
+0:?           0.000000
+0:?           0.000000
+0:7        Constant:
+0:7          0.000000
+0:?         Constant:
+0:?           0 (const int)
+0:?           0 (const int)
+0:9      Branch: Return with expression
+0:9        Constant:
+0:9          0.000000
+0:9          0.000000
+0:9          0.000000
+0:9          0.000000
+0:6  Function Definition: main( ( temp void)
+0:6    Function Parameters: 
+0:?     Sequence
+0:6      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:6        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_shadowTex' ( uniform texture2D)
+0:?     'g_shadowSampler' ( uniform sampler)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+SPIR-V is not generated for failed compile or link
diff --git a/Test/hlsl.samplecmp.negative.frag b/Test/hlsl.samplecmp.negative.frag
new file mode 100644
index 0000000..cea87bd
--- /dev/null
+++ b/Test/hlsl.samplecmp.negative.frag
@@ -0,0 +1,12 @@
+
+Texture2D g_shadowTex;
+SamplerState g_shadowSampler;
+SamplerComparisonState g_shadowSamplerComp;
+
+float4 main() : SV_Target0
+{
+    g_shadowTex.SampleCmp(g_shadowSamplerComp, float2(0,0), 0); // OK
+    g_shadowTex.SampleCmp(g_shadowSampler, float2(0,0), 0);     // ERROR (should be comparison sampler)
+
+    return 0;
+}
diff --git a/Test/hlsl.samplecmp.negative2.frag b/Test/hlsl.samplecmp.negative2.frag
new file mode 100644
index 0000000..33a2133
--- /dev/null
+++ b/Test/hlsl.samplecmp.negative2.frag
@@ -0,0 +1,10 @@
+
+Texture2D g_shadowTex;
+SamplerState g_shadowSampler;
+
+float4 main() : SV_Target0
+{
+    g_shadowTex.GatherCmpRed(g_shadowSampler, float2(0,0), 0, int2(0,0));  // ERROR (should be comparison sampler)
+
+    return 0;
+}
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 2889e1a..b23674e 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -212,6 +212,8 @@
         {"hlsl.samplecmp.basic.dx10.frag", "main"},
         {"hlsl.samplecmp.offset.dx10.frag", "main"},
         {"hlsl.samplecmp.offsetarray.dx10.frag", "main"},
+        {"hlsl.samplecmp.negative.frag", "main"},
+        {"hlsl.samplecmp.negative2.frag", "main"},
         {"hlsl.samplecmplevelzero.array.dx10.frag", "main"},
         {"hlsl.samplecmplevelzero.basic.dx10.frag", "main"},
         {"hlsl.samplecmplevelzero.offset.dx10.frag", "main"},
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 4ba0d87..6a6cb3f 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -3144,6 +3144,18 @@
             TIntermTyped* argCmpVal = argAggregate->getSequence()[3]->getAsTyped();
             TIntermTyped* argOffset = nullptr;
 
+            // Sampler argument should be a sampler.
+            if (argSamp->getType().getBasicType() != EbtSampler) {
+                error(loc, "expected: sampler type", "", "");
+                return;
+            }
+
+            // Sampler should be a SamplerComparisonState
+            if (! argSamp->getType().getSampler().isShadow()) {
+                error(loc, "expected: SamplerComparisonState", "", "");
+                return;
+            }
+
             // optional offset value
             if (argAggregate->getSequence().size() > 4)
                 argOffset = argAggregate->getSequence()[4]->getAsTyped();
@@ -3381,6 +3393,18 @@
             bool hasOffset1    = false;
             bool hasOffset4    = false;
 
+            // Sampler argument should be a sampler.
+            if (argSamp->getType().getBasicType() != EbtSampler) {
+                error(loc, "expected: sampler type", "", "");
+                return;
+            }
+
+            // Cmp forms require SamplerComparisonState
+            if (cmpValues > 0 && ! argSamp->getType().getSampler().isShadow()) {
+                error(loc, "expected: SamplerComparisonState", "", "");
+                return;
+            }
+
             // Only 2D forms can have offsets.  Discover if we have 0, 1 or 4 offsets.
             if (dim == Esd2D) {
                 hasOffset1 = (argSize == (4+cmpValues) || argSize == (5+cmpValues));