HLSL: add subpass input types and methods

Add support for Subpass Input proposal of issue #1069.

Subpass input types are given as:

    layout(input_attachment_index = 1) SubpassInput<float4> subpass_f;
    layout(input_attachment_index = 2) SubpassInput<int4>   subpass_i;
    layout(input_attachment_index = 3) SubpassInput<uint4>  subpass_u;

    layout(input_attachment_index = 1) SubpassInputMS<float4> subpass_ms_f;
    layout(input_attachment_index = 2) SubpassInputMS<int4>   subpass_ms_i;
    layout(input_attachment_index = 3) SubpassInputMS<uint4>  subpass_ms_u;

The input attachment may also be specified using attribute syntax:

    [[vk::input_attachment_index(7)]] SubpassInput subpass_2;

The template type may be a shorter-than-vec4 vector, but currently user
structs are not supported.  (An unimplemented error will be issued).

The load operations are methods on objects of the above type:

    float4 result = subpass_f.SubpassLoad();
    int4   result = subpass_i.SubpassLoad();
    uint4  result = subpass_u.SubpassLoad();

    float4 result = subpass_ms_f.SubpassLoad(samp);
    int4   result = subpass_ms_i.SubpassLoad(samp);
    uint4  result = subpass_ms_u.SubpassLoad(samp);

Additionally, the AST printer could not print EOpSubpass* nodes.  Now it can.

Fixes #1069
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index 4914f20..88eacd9 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -1088,6 +1088,69 @@
     return true;
 }
 
+// subpass input type
+//      : SUBPASSINPUT
+//      | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
+//      | SUBPASSINPUTMS
+//      | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
+bool HlslGrammar::acceptSubpassInputType(TType& type)
+{
+    // read subpass type
+    const EHlslTokenClass subpassInputType = peek();
+
+    bool multisample;
+
+    switch (subpassInputType) {
+    case EHTokSubpassInput:   multisample = false; break;
+    case EHTokSubpassInputMS: multisample = true;  break;
+    default:
+        return false;  // not a subpass input declaration
+    }
+
+    advanceToken();  // consume the sampler type keyword
+
+    TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4
+
+    if (acceptTokenClass(EHTokLeftAngle)) {
+        if (! acceptType(subpassType)) {
+            expected("scalar or vector type");
+            return false;
+        }
+
+        const TBasicType basicRetType = subpassType.getBasicType() ;
+
+        switch (basicRetType) {
+        case EbtFloat:
+        case EbtUint:
+        case EbtInt:
+        case EbtStruct:
+            break;
+        default:
+            unimplemented("basic type in subpass input");
+            return false;
+        }
+
+        if (! acceptTokenClass(EHTokRightAngle)) {
+            expected("right angle bracket");
+            return false;
+        }
+    }
+
+    const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType()
+        : subpassType.getBasicType();
+
+    TSampler sampler;
+    sampler.setSubpass(subpassBasicType, multisample);
+
+    // Remember the declared return type.  Function returns false on error.
+    if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc))
+        return false;
+
+    type.shallowCopy(TType(sampler, EvqUniform));
+
+    return true;
+}
+
 // sampler_type
 //      : SAMPLER
 //      | SAMPLER1D
@@ -1357,6 +1420,11 @@
         return acceptSamplerType(type);
         break;
 
+    case EHTokSubpassInput:           // fall through
+    case EHTokSubpassInputMS:         // ...
+        return acceptSubpassInputType(type);
+        break;
+
     case EHTokBuffer:                 // fall through
     case EHTokTexture1d:              // ...
     case EHTokTexture1darray:         // ...