Vulkan: SPIR-V Gen: Fixes to tessellation builtins

On TCS, TES and FS, gl_PrimitiveID is actually an input.  Additionally,
`patch` variables (including gl_TessLevel* built-ins) need to be
decorated with Patch.

Bug: angleproject:4889
Change-Id: I326ec4b0c011fe8eaafbad4f8bcb0f537005f96f
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3048320
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Tim Van Patten <timvp@google.com>
diff --git a/src/compiler/translator/OutputSPIRV.cpp b/src/compiler/translator/OutputSPIRV.cpp
index d41c8ef..b00709f 100644
--- a/src/compiler/translator/OutputSPIRV.cpp
+++ b/src/compiler/translator/OutputSPIRV.cpp
@@ -463,7 +463,6 @@
 
         case EvqFragDepth:
         case EvqSampleMask:
-        case EvqPrimitiveID:
             return spv::StorageClassOutput;
 
         case EvqTessLevelOuter:
@@ -473,7 +472,9 @@
                                                             : spv::StorageClassInput;
 
         case EvqLayer:
+        case EvqPrimitiveID:
             // gl_Layer is output in GS and input in FS.
+            // gl_PrimitiveID is output in GS and input in TCS, TES and FS.
             return shaderType == GL_GEOMETRY_SHADER ? spv::StorageClassOutput
                                                     : spv::StorageClassInput;
 
@@ -645,6 +646,12 @@
     spirv::WriteDecorate(mBuilder.getSpirvDecorations(), varId, spv::DecorationBuiltIn,
                          {spirv::LiteralInteger(builtInDecoration)});
 
+    // Additionally, decorate gl_TessLevel* with Patch.
+    if (type.getQualifier() == EvqTessLevelInner || type.getQualifier() == EvqTessLevelOuter)
+    {
+        spirv::WriteDecorate(mBuilder.getSpirvDecorations(), varId, spv::DecorationPatch, {});
+    }
+
     mSymbolIdMap.insert({symbol, varId});
     return varId;
 }
@@ -5756,6 +5763,13 @@
             spirv::WriteDecorate(mBuilder.getSpirvDecorations(), nonArrayTypeId,
                                  spv::DecorationBlock, {});
         }
+
+        // Tessellation shaders can have their input or output qualified with |patch|.
+        if (type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut)
+        {
+            spirv::WriteDecorate(mBuilder.getSpirvDecorations(), nonArrayTypeId,
+                                 spv::DecorationPatch, {});
+        }
     }
     else if (isInterfaceBlock)
     {