From ccb076ac9b1fa9c8fdb82481ae67832e9d60c365 Mon Sep 17 00:00:00 2001
From: steve-lunarg <steve_gh@khasekhemwy.net>
Date: Wed, 5 Apr 2017 11:03:02 -0600
Subject: [PATCH] HLSL: allow non-vec3 tessellation coordinate declarations

HLSL requires vec2 tessellation coordinate declarations in some cases
(e.g, isoline topology), where SPIR-V requires the TessCoord qualified
builtin to be a vec3 in all cases.  This alters the IO form of the
variable to be a vec3, which will be copied to the shader's declared
type if needed.  This is not a validation; the shader type must be correct.
---
 Test/baseResults/hlsl.domain.3.tese.out | 392 ++++++++++++++++++++++++
 Test/hlsl.domain.3.tese                 |  31 ++
 gtests/Hlsl.FromFile.cpp                |   1 +
 hlsl/hlslParseHelper.cpp                |  46 ++-
 hlsl/hlslParseHelper.h                  |   2 +-
 5 files changed, 457 insertions(+), 15 deletions(-)
 create mode 100644 Test/baseResults/hlsl.domain.3.tese.out
 create mode 100644 Test/hlsl.domain.3.tese

diff --git a/Test/baseResults/hlsl.domain.3.tese.out b/Test/baseResults/hlsl.domain.3.tese.out
new file mode 100644
index 000000000..1c7b713e4
--- /dev/null
+++ b/Test/baseResults/hlsl.domain.3.tese.out
@@ -0,0 +1,392 @@
+hlsl.domain.3.tese
+Shader version: 450
+input primitive = isolines
+vertex spacing = none
+triangle order = none
+0:? Sequence
+0:24  Function Definition: @main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11; ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24    Function Parameters: 
+0:24      'i' ( const (read only) 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24      'tesscoord' ( in 2-component vector of float)
+0:24      'pcf_data' ( in structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:?     Sequence
+0:27      move second child to first child ( temp 4-component vector of float)
+0:27        pos: direct index for structure ( temp 4-component vector of float)
+0:27          'o' ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:27          Constant:
+0:27            0 (const int)
+0:27        add ( temp 4-component vector of float)
+0:27          pos: direct index for structure ( temp 4-component vector of float)
+0:27            direct index ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:27              'i' ( const (read only) 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:27              Constant:
+0:27                0 (const int)
+0:27            Constant:
+0:27              0 (const int)
+0:27          direct index ( temp float)
+0:27            'tesscoord' ( in 2-component vector of float)
+0:27            Constant:
+0:27              0 (const int)
+0:28      move second child to first child ( temp 3-component vector of float)
+0:28        norm: direct index for structure ( temp 3-component vector of float)
+0:28          'o' ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:28          Constant:
+0:28            1 (const int)
+0:28        add ( temp 3-component vector of float)
+0:28          norm: direct index for structure ( temp 3-component vector of float)
+0:28            direct index ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:28              'i' ( const (read only) 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:28              Constant:
+0:28                0 (const int)
+0:28            Constant:
+0:28              1 (const int)
+0:28          direct index ( temp float)
+0:28            'tesscoord' ( in 2-component vector of float)
+0:28            Constant:
+0:28              1 (const int)
+0:30      Branch: Return with expression
+0:30        'o' ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24  Function Definition: main( ( temp void)
+0:24    Function Parameters: 
+0:?     Sequence
+0:24      move second child to first child ( temp 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?         'i' ( temp 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?         'i' (layout( location=0) in 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24      move second child to first child ( temp 2-component vector of float)
+0:?         'tesscoord' ( temp 2-component vector of float)
+0:?         Construct vec2 ( temp 2-component vector of float)
+0:?           'tesscoord' ( patch in 3-component vector of float TessCoord)
+0:24      Sequence
+0:24        move second child to first child ( temp float)
+0:24          direct index ( temp float)
+0:24            flTessFactor: direct index for structure ( temp 3-element array of float)
+0:?               'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24              Constant:
+0:24                0 (const int)
+0:24            Constant:
+0:24              0 (const int)
+0:24          direct index ( patch in float TessLevelOuter)
+0:?             'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:24            Constant:
+0:24              0 (const int)
+0:24        move second child to first child ( temp float)
+0:24          direct index ( temp float)
+0:24            flTessFactor: direct index for structure ( temp 3-element array of float)
+0:?               'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24              Constant:
+0:24                0 (const int)
+0:24            Constant:
+0:24              1 (const int)
+0:24          direct index ( patch in float TessLevelOuter)
+0:?             'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:24            Constant:
+0:24              1 (const int)
+0:24        move second child to first child ( temp float)
+0:24          direct index ( temp float)
+0:24            flTessFactor: direct index for structure ( temp 3-element array of float)
+0:?               'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24              Constant:
+0:24                0 (const int)
+0:24            Constant:
+0:24              2 (const int)
+0:24          direct index ( patch in float TessLevelOuter)
+0:?             'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:24            Constant:
+0:24              2 (const int)
+0:24        move second child to first child ( temp float)
+0:24          flInsideTessFactor: direct index for structure ( temp float)
+0:?             'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24            Constant:
+0:24              1 (const int)
+0:24          direct index ( patch in float TessLevelInner)
+0:?             'pcf_data_flInsideTessFactor' ( patch in 2-element array of float TessLevelInner)
+0:24            Constant:
+0:24              0 (const int)
+0:24      move second child to first child ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?         '@entryPointOutput' (layout( location=0) out structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24        Function Call: @main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11; ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?           'i' ( temp 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?           'tesscoord' ( temp 2-component vector of float)
+0:?           'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?     'i' (layout( location=0) in 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?     'tesscoord' ( patch in 3-component vector of float TessCoord)
+0:?     'pcf_data' (layout( location=2) patch in structure{})
+0:?     'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:?     'pcf_data_flInsideTessFactor' ( patch in 2-element array of float TessLevelInner)
+
+
+Linked tessellation evaluation stage:
+
+
+Shader version: 450
+input primitive = isolines
+vertex spacing = none
+triangle order = none
+0:? Sequence
+0:24  Function Definition: @main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11; ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24    Function Parameters: 
+0:24      'i' ( const (read only) 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24      'tesscoord' ( in 2-component vector of float)
+0:24      'pcf_data' ( in structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:?     Sequence
+0:27      move second child to first child ( temp 4-component vector of float)
+0:27        pos: direct index for structure ( temp 4-component vector of float)
+0:27          'o' ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:27          Constant:
+0:27            0 (const int)
+0:27        add ( temp 4-component vector of float)
+0:27          pos: direct index for structure ( temp 4-component vector of float)
+0:27            direct index ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:27              'i' ( const (read only) 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:27              Constant:
+0:27                0 (const int)
+0:27            Constant:
+0:27              0 (const int)
+0:27          direct index ( temp float)
+0:27            'tesscoord' ( in 2-component vector of float)
+0:27            Constant:
+0:27              0 (const int)
+0:28      move second child to first child ( temp 3-component vector of float)
+0:28        norm: direct index for structure ( temp 3-component vector of float)
+0:28          'o' ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:28          Constant:
+0:28            1 (const int)
+0:28        add ( temp 3-component vector of float)
+0:28          norm: direct index for structure ( temp 3-component vector of float)
+0:28            direct index ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:28              'i' ( const (read only) 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:28              Constant:
+0:28                0 (const int)
+0:28            Constant:
+0:28              1 (const int)
+0:28          direct index ( temp float)
+0:28            'tesscoord' ( in 2-component vector of float)
+0:28            Constant:
+0:28              1 (const int)
+0:30      Branch: Return with expression
+0:30        'o' ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24  Function Definition: main( ( temp void)
+0:24    Function Parameters: 
+0:?     Sequence
+0:24      move second child to first child ( temp 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?         'i' ( temp 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?         'i' (layout( location=0) in 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24      move second child to first child ( temp 2-component vector of float)
+0:?         'tesscoord' ( temp 2-component vector of float)
+0:?         Construct vec2 ( temp 2-component vector of float)
+0:?           'tesscoord' ( patch in 3-component vector of float TessCoord)
+0:24      Sequence
+0:24        move second child to first child ( temp float)
+0:24          direct index ( temp float)
+0:24            flTessFactor: direct index for structure ( temp 3-element array of float)
+0:?               'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24              Constant:
+0:24                0 (const int)
+0:24            Constant:
+0:24              0 (const int)
+0:24          direct index ( patch in float TessLevelOuter)
+0:?             'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:24            Constant:
+0:24              0 (const int)
+0:24        move second child to first child ( temp float)
+0:24          direct index ( temp float)
+0:24            flTessFactor: direct index for structure ( temp 3-element array of float)
+0:?               'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24              Constant:
+0:24                0 (const int)
+0:24            Constant:
+0:24              1 (const int)
+0:24          direct index ( patch in float TessLevelOuter)
+0:?             'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:24            Constant:
+0:24              1 (const int)
+0:24        move second child to first child ( temp float)
+0:24          direct index ( temp float)
+0:24            flTessFactor: direct index for structure ( temp 3-element array of float)
+0:?               'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24              Constant:
+0:24                0 (const int)
+0:24            Constant:
+0:24              2 (const int)
+0:24          direct index ( patch in float TessLevelOuter)
+0:?             'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:24            Constant:
+0:24              2 (const int)
+0:24        move second child to first child ( temp float)
+0:24          flInsideTessFactor: direct index for structure ( temp float)
+0:?             'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:24            Constant:
+0:24              1 (const int)
+0:24          direct index ( patch in float TessLevelInner)
+0:?             'pcf_data_flInsideTessFactor' ( patch in 2-element array of float TessLevelInner)
+0:24            Constant:
+0:24              0 (const int)
+0:24      move second child to first child ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?         '@entryPointOutput' (layout( location=0) out structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:24        Function Call: @main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11; ( temp structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?           'i' ( temp 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?           'tesscoord' ( temp 2-component vector of float)
+0:?           'pcf_data' ( temp structure{ temp 3-element array of float flTessFactor,  temp float flInsideTessFactor})
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?     'i' (layout( location=0) in 2-element array of structure{ temp 4-component vector of float pos,  temp 3-component vector of float norm})
+0:?     'tesscoord' ( patch in 3-component vector of float TessCoord)
+0:?     'pcf_data' (layout( location=2) patch in structure{})
+0:?     'pcf_data_flTessFactor' ( patch in 4-element array of float TessLevelOuter)
+0:?     'pcf_data_flInsideTessFactor' ( patch in 2-element array of float TessLevelInner)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 96
+
+                              Capability Tessellation
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint TessellationEvaluation 4  "main" 54 58 67 81 86 95
+                              ExecutionMode 4 Isolines
+                              Name 4  "main"
+                              Name 9  "ds_in_t"
+                              MemberName 9(ds_in_t) 0  "pos"
+                              MemberName 9(ds_in_t) 1  "norm"
+                              Name 17  "pcf_in_t"
+                              MemberName 17(pcf_in_t) 0  "flTessFactor"
+                              MemberName 17(pcf_in_t) 1  "flInsideTessFactor"
+                              Name 19  "gs_in_t"
+                              MemberName 19(gs_in_t) 0  "pos"
+                              MemberName 19(gs_in_t) 1  "norm"
+                              Name 24  "@main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11;"
+                              Name 21  "i"
+                              Name 22  "tesscoord"
+                              Name 23  "pcf_data"
+                              Name 27  "o"
+                              Name 52  "i"
+                              Name 54  "i"
+                              Name 56  "tesscoord"
+                              Name 58  "tesscoord"
+                              Name 63  "pcf_data"
+                              Name 67  "pcf_data_flTessFactor"
+                              Name 81  "pcf_data_flInsideTessFactor"
+                              Name 86  "@entryPointOutput"
+                              Name 88  "param"
+                              Name 90  "param"
+                              Name 93  "pcf_in_t"
+                              Name 95  "pcf_data"
+                              Decorate 54(i) Location 0
+                              Decorate 58(tesscoord) Patch
+                              Decorate 58(tesscoord) BuiltIn TessCoord
+                              Decorate 67(pcf_data_flTessFactor) Patch
+                              Decorate 67(pcf_data_flTessFactor) BuiltIn TessLevelOuter
+                              Decorate 81(pcf_data_flInsideTessFactor) Patch
+                              Decorate 81(pcf_data_flInsideTessFactor) BuiltIn TessLevelInner
+                              Decorate 86(@entryPointOutput) Location 0
+                              Decorate 95(pcf_data) Patch
+                              Decorate 95(pcf_data) Location 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeVector 6(float) 3
+      9(ds_in_t):             TypeStruct 7(fvec4) 8(fvec3)
+              10:             TypeInt 32 0
+              11:     10(int) Constant 2
+              12:             TypeArray 9(ds_in_t) 11
+              13:             TypeVector 6(float) 2
+              14:             TypePointer Function 13(fvec2)
+              15:     10(int) Constant 3
+              16:             TypeArray 6(float) 15
+    17(pcf_in_t):             TypeStruct 16 6(float)
+              18:             TypePointer Function 17(pcf_in_t)
+     19(gs_in_t):             TypeStruct 7(fvec4) 8(fvec3)
+              20:             TypeFunction 19(gs_in_t) 12 14(ptr) 18(ptr)
+              26:             TypePointer Function 19(gs_in_t)
+              28:             TypeInt 32 1
+              29:     28(int) Constant 0
+              31:     10(int) Constant 0
+              32:             TypePointer Function 6(float)
+              37:             TypePointer Function 7(fvec4)
+              39:     28(int) Constant 1
+              41:     10(int) Constant 1
+              46:             TypePointer Function 8(fvec3)
+              51:             TypePointer Function 12
+              53:             TypePointer Input 12
+           54(i):     53(ptr) Variable Input
+              57:             TypePointer Input 8(fvec3)
+   58(tesscoord):     57(ptr) Variable Input
+              64:     10(int) Constant 4
+              65:             TypeArray 6(float) 64
+              66:             TypePointer Input 65
+67(pcf_data_flTessFactor):     66(ptr) Variable Input
+              68:             TypePointer Input 6(float)
+              75:     28(int) Constant 2
+              79:             TypeArray 6(float) 11
+              80:             TypePointer Input 79
+81(pcf_data_flInsideTessFactor):     80(ptr) Variable Input
+              85:             TypePointer Output 19(gs_in_t)
+86(@entryPointOutput):     85(ptr) Variable Output
+    93(pcf_in_t):             TypeStruct
+              94:             TypePointer Input 93(pcf_in_t)
+    95(pcf_data):     94(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+           52(i):     51(ptr) Variable Function
+   56(tesscoord):     14(ptr) Variable Function
+    63(pcf_data):     18(ptr) Variable Function
+       88(param):     14(ptr) Variable Function
+       90(param):     18(ptr) Variable Function
+              55:          12 Load 54(i)
+                              Store 52(i) 55
+              59:    8(fvec3) Load 58(tesscoord)
+              60:    6(float) CompositeExtract 59 0
+              61:    6(float) CompositeExtract 59 1
+              62:   13(fvec2) CompositeConstruct 60 61
+                              Store 56(tesscoord) 62
+              69:     68(ptr) AccessChain 67(pcf_data_flTessFactor) 29
+              70:    6(float) Load 69
+              71:     32(ptr) AccessChain 63(pcf_data) 29 29
+                              Store 71 70
+              72:     68(ptr) AccessChain 67(pcf_data_flTessFactor) 39
+              73:    6(float) Load 72
+              74:     32(ptr) AccessChain 63(pcf_data) 29 39
+                              Store 74 73
+              76:     68(ptr) AccessChain 67(pcf_data_flTessFactor) 75
+              77:    6(float) Load 76
+              78:     32(ptr) AccessChain 63(pcf_data) 29 75
+                              Store 78 77
+              82:     68(ptr) AccessChain 81(pcf_data_flInsideTessFactor) 29
+              83:    6(float) Load 82
+              84:     32(ptr) AccessChain 63(pcf_data) 39
+                              Store 84 83
+              87:          12 Load 52(i)
+              89:   13(fvec2) Load 56(tesscoord)
+                              Store 88(param) 89
+              91:17(pcf_in_t) Load 63(pcf_data)
+                              Store 90(param) 91
+              92: 19(gs_in_t) FunctionCall 24(@main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11;) 87 88(param) 90(param)
+                              Store 86(@entryPointOutput) 92
+                              Return
+                              FunctionEnd
+24(@main(struct-ds_in_t-vf4-vf31[2];vf2;struct-pcf_in_t-f1[3]-f11;): 19(gs_in_t) Function None 20
+           21(i):          12 FunctionParameter
+   22(tesscoord):     14(ptr) FunctionParameter
+    23(pcf_data):     18(ptr) FunctionParameter
+              25:             Label
+           27(o):     26(ptr) Variable Function
+              30:    7(fvec4) CompositeExtract 21(i) 0 0
+              33:     32(ptr) AccessChain 22(tesscoord) 31
+              34:    6(float) Load 33
+              35:    7(fvec4) CompositeConstruct 34 34 34 34
+              36:    7(fvec4) FAdd 30 35
+              38:     37(ptr) AccessChain 27(o) 29
+                              Store 38 36
+              40:    8(fvec3) CompositeExtract 21(i) 0 1
+              42:     32(ptr) AccessChain 22(tesscoord) 41
+              43:    6(float) Load 42
+              44:    8(fvec3) CompositeConstruct 43 43 43
+              45:    8(fvec3) FAdd 40 44
+              47:     46(ptr) AccessChain 27(o) 39
+                              Store 47 45
+              48: 19(gs_in_t) Load 27(o)
+                              ReturnValue 48
+                              FunctionEnd
diff --git a/Test/hlsl.domain.3.tese b/Test/hlsl.domain.3.tese
new file mode 100644
index 000000000..aeceedacb
--- /dev/null
+++ b/Test/hlsl.domain.3.tese
@@ -0,0 +1,31 @@
+// Test vec2 tessellation coordinate: the IO form should be a vec3, copied to a vec2
+// at the entry point boundary.
+
+struct ds_in_t 
+{ 
+    float4 pos  : POSITION; 
+    float3 norm : TEXCOORD0; 
+}; 
+
+struct pcf_in_t 
+{ 
+    float flTessFactor [3]   : SV_TessFactor; 
+    float flInsideTessFactor : SV_InsideTessFactor; 
+}; 
+
+struct gs_in_t 
+{ 
+    float4 pos  : POSITION; 
+    float3 norm : TEXCOORD0; 
+}; 
+
+[domain ( "isoline" )]
+gs_in_t main (const OutputPatch <ds_in_t, 2> i, float2 tesscoord : SV_DomainLocation, pcf_in_t pcf_data ) 
+{ 
+    gs_in_t o; 
+
+    o.pos  = i[0].pos + tesscoord.x;
+    o.norm = i[0].norm + tesscoord.y;
+
+    return o; 
+}
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 6bad94e2f..db5bc2ac6 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -125,6 +125,7 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.getsampleposition.dx10.frag", "main"},
         {"hlsl.domain.1.tese", "main"},
         {"hlsl.domain.2.tese", "main"},
+        {"hlsl.domain.3.tese", "main"},
         {"hlsl.hull.1.tesc", "main"},
         {"hlsl.hull.2.tesc", "main"},
         {"hlsl.hull.void.tesc", "main"},
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index df67d1e9e..935365c8e 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -1042,7 +1042,7 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru
             if (arraySizes)
                 ioVar->getWritableType().newArraySizes(*arraySizes);
 
-            fixBuiltInArrayType(ioVar->getWritableType());
+            fixBuiltInIoType(ioVar->getWritableType());
 
             interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar;
 
@@ -1382,28 +1382,44 @@ void HlslParseContext::trackLinkage(TSymbol& symbol)
 // Some types require fixed array sizes in SPIR-V, but can be scalars or
 // arrays of sizes SPIR-V doesn't allow.  For example, tessellation factors.
 // This creates the right size.  A conversion is performed when the internal
-// type is copied to or from the external type.
-void HlslParseContext::fixBuiltInArrayType(TType& type)
+// type is copied to or from the external type.  This corrects the externally
+// facing input or output type to abide downstream semantics.
+void HlslParseContext::fixBuiltInIoType(TType& type)
 {
-    int requiredSize = 0;
+    int requiredArraySize = 0;
 
     switch (type.getQualifier().builtIn) {
-    case EbvTessLevelOuter: requiredSize = 4; break;
-    case EbvTessLevelInner: requiredSize = 2; break;
+    case EbvTessLevelOuter: requiredArraySize = 4; break;
+    case EbvTessLevelInner: requiredArraySize = 2; break;
     case EbvClipDistance:   // TODO: ...
     case EbvCullDistance:   // TODO: ...
+        return;
+    case EbvTessCoord:
+        {
+            // tesscoord is always a vec3 for the IO variable, no matter the shader's
+            // declared vector size.
+            TType tessCoordType(type.getBasicType(), type.getQualifier().storage, 3);
+
+            tessCoordType.getQualifier() = type.getQualifier();
+            type.shallowCopy(tessCoordType);
+
+            break;
+        }
     default:
         return;
     }
 
-    if (type.isArray()) {
-        // Already an array.  Fix the size.
-        type.changeOuterArraySize(requiredSize);
-    } else {
-        // it wasn't an array, but needs to be.
-        TArraySizes arraySizes;
-        arraySizes.addInnerSize(requiredSize);
-        type.newArraySizes(arraySizes);
+    // Alter or set array size as needed.
+    if (requiredArraySize > 0) {
+        if (type.isArray()) {
+            // Already an array.  Fix the size.
+            type.changeOuterArraySize(requiredArraySize);
+        } else {
+            // it wasn't an array, but needs to be.
+            TArraySizes arraySizes;
+            arraySizes.addInnerSize(requiredArraySize);
+            type.newArraySizes(arraySizes);
+        }
     }
 }
 
@@ -1985,6 +2001,8 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return
         }
         ioVariable->getWritableType().getQualifier().storage = storage;
 
+        fixBuiltInIoType(ioVariable->getWritableType());
+
         return ioVariable;
     };
 
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 7fd06e9fb..14c9809ea 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -250,7 +250,7 @@ protected:
     void addInterstageIoToLinkage();
     void addPatchConstantInvocation();
 
-    void fixBuiltInArrayType(TType&);
+    void fixBuiltInIoType(TType&);
 
     void flatten(const TSourceLoc& loc, const TVariable& variable);
     int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
-- 
GitLab