Commit 194f0f39 by steve-lunarg

HLSL: require tessellation factors to be fixed size arrays

SPIR-V requires that tessellation factor arrays be size 4 (outer) or 2 (inner). HLSL allows other sizes such as 3, or even scalars. This commit converts between them by forcing the IO types to be the SPIR-V size, and allowing copies between the internal and IO types to handle these cases.
parent 9cee73e0
...@@ -51,7 +51,7 @@ vertices = 4 ...@@ -51,7 +51,7 @@ vertices = 4
0:? Sequence 0:? Sequence
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 0 (const int) 0:? 0 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -63,7 +63,7 @@ vertices = 4 ...@@ -63,7 +63,7 @@ vertices = 4
0:? 0 (const int) 0:? 0 (const int)
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 1 (const int) 0:? 1 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -105,7 +105,7 @@ vertices = 4 ...@@ -105,7 +105,7 @@ vertices = 4
0:? 'm_cpid' ( in uint InvocationID) 0:? 'm_cpid' ( in uint InvocationID)
0:? 'pid' ( in uint PrimitiveID) 0:? 'pid' ( in uint PrimitiveID)
0:? '@patchConstantOutput' (layout( location=1) patch out structure{}) 0:? '@patchConstantOutput' (layout( location=1) patch out structure{})
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
Linked tessellation control stage: Linked tessellation control stage:
...@@ -163,7 +163,7 @@ vertices = 4 ...@@ -163,7 +163,7 @@ vertices = 4
0:? Sequence 0:? Sequence
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 0 (const int) 0:? 0 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -175,7 +175,7 @@ vertices = 4 ...@@ -175,7 +175,7 @@ vertices = 4
0:? 0 (const int) 0:? 0 (const int)
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 1 (const int) 0:? 1 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -217,16 +217,16 @@ vertices = 4 ...@@ -217,16 +217,16 @@ vertices = 4
0:? 'm_cpid' ( in uint InvocationID) 0:? 'm_cpid' ( in uint InvocationID)
0:? 'pid' ( in uint PrimitiveID) 0:? 'pid' ( in uint PrimitiveID)
0:? '@patchConstantOutput' (layout( location=1) patch out structure{}) 0:? '@patchConstantOutput' (layout( location=1) patch out structure{})
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 88 // Id's are bound by 89
Capability Tessellation Capability Tessellation
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationControl 4 "main" 40 44 47 62 67 87 EntryPoint TessellationControl 4 "main" 40 44 47 62 68 88
ExecutionMode 4 OutputVertices 4 ExecutionMode 4 OutputVertices 4
Name 4 "main" Name 4 "main"
Name 8 "VS_OUT" Name 8 "VS_OUT"
...@@ -251,18 +251,18 @@ vertices = 4 ...@@ -251,18 +251,18 @@ vertices = 4
Name 61 "@patchConstantResult" Name 61 "@patchConstantResult"
Name 62 "pid" Name 62 "pid"
Name 63 "param" Name 63 "param"
Name 67 "@patchConstantOutput_edges" Name 68 "@patchConstantOutput_edges"
Name 77 "output" Name 78 "output"
Name 85 "HS_CONSTANT_OUT" Name 86 "HS_CONSTANT_OUT"
Name 87 "@patchConstantOutput" Name 88 "@patchConstantOutput"
Decorate 40(ip) Location 0 Decorate 40(ip) Location 0
Decorate 44(m_cpid) BuiltIn InvocationId Decorate 44(m_cpid) BuiltIn InvocationId
Decorate 47(@entryPointOutput) Location 0 Decorate 47(@entryPointOutput) Location 0
Decorate 62(pid) BuiltIn PrimitiveId Decorate 62(pid) BuiltIn PrimitiveId
Decorate 67(@patchConstantOutput_edges) Patch Decorate 68(@patchConstantOutput_edges) Patch
Decorate 67(@patchConstantOutput_edges) BuiltIn TessLevelOuter Decorate 68(@patchConstantOutput_edges) BuiltIn TessLevelOuter
Decorate 87(@patchConstantOutput) Patch Decorate 88(@patchConstantOutput) Patch
Decorate 87(@patchConstantOutput) Location 1 Decorate 88(@patchConstantOutput) Location 1
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeFloat 32 6: TypeFloat 32
...@@ -294,16 +294,17 @@ vertices = 4 ...@@ -294,16 +294,17 @@ vertices = 4
56: TypeBool 56: TypeBool
60: TypePointer Function 22(HS_CONSTANT_OUT) 60: TypePointer Function 22(HS_CONSTANT_OUT)
62(pid): 43(ptr) Variable Input 62(pid): 43(ptr) Variable Input
66: TypePointer Output 21 66: TypeArray 6(float) 10
67(@patchConstantOutput_edges): 66(ptr) Variable Output 67: TypePointer Output 66
68: TypePointer Function 6(float) 68(@patchConstantOutput_edges): 67(ptr) Variable Output
71: TypePointer Output 6(float) 69: TypePointer Function 6(float)
73: 29(int) Constant 1 72: TypePointer Output 6(float)
78: 6(float) Constant 1073741824 74: 29(int) Constant 1
80: 6(float) Constant 1090519040 79: 6(float) Constant 1073741824
85(HS_CONSTANT_OUT): TypeStruct 81: 6(float) Constant 1090519040
86: TypePointer Output 85(HS_CONSTANT_OUT) 86(HS_CONSTANT_OUT): TypeStruct
87(@patchConstantOutput): 86(ptr) Variable Output 87: TypePointer Output 86(HS_CONSTANT_OUT)
88(@patchConstantOutput): 87(ptr) Variable Output
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
38(ip): 12(ptr) Variable Function 38(ip): 12(ptr) Variable Function
...@@ -332,14 +333,14 @@ vertices = 4 ...@@ -332,14 +333,14 @@ vertices = 4
Store 63(param) 64 Store 63(param) 64
65:22(HS_CONSTANT_OUT) FunctionCall 25(PCF(u1;) 63(param) 65:22(HS_CONSTANT_OUT) FunctionCall 25(PCF(u1;) 63(param)
Store 61(@patchConstantResult) 65 Store 61(@patchConstantResult) 65
69: 68(ptr) AccessChain 61(@patchConstantResult) 30 30 70: 69(ptr) AccessChain 61(@patchConstantResult) 30 30
70: 6(float) Load 69 71: 6(float) Load 70
72: 71(ptr) AccessChain 67(@patchConstantOutput_edges) 30 73: 72(ptr) AccessChain 68(@patchConstantOutput_edges) 30
Store 72 70 Store 73 71
74: 68(ptr) AccessChain 61(@patchConstantResult) 30 73 75: 69(ptr) AccessChain 61(@patchConstantResult) 30 74
75: 6(float) Load 74 76: 6(float) Load 75
76: 71(ptr) AccessChain 67(@patchConstantOutput_edges) 73 77: 72(ptr) AccessChain 68(@patchConstantOutput_edges) 74
Store 76 75 Store 77 76
Branch 59 Branch 59
59: Label 59: Label
Return Return
...@@ -359,11 +360,11 @@ vertices = 4 ...@@ -359,11 +360,11 @@ vertices = 4
25(PCF(u1;):22(HS_CONSTANT_OUT) Function None 23 25(PCF(u1;):22(HS_CONSTANT_OUT) Function None 23
24(pid): 13(ptr) FunctionParameter 24(pid): 13(ptr) FunctionParameter
26: Label 26: Label
77(output): 60(ptr) Variable Function 78(output): 60(ptr) Variable Function
79: 68(ptr) AccessChain 77(output) 30 30 80: 69(ptr) AccessChain 78(output) 30 30
Store 79 78 Store 80 79
81: 68(ptr) AccessChain 77(output) 30 73 82: 69(ptr) AccessChain 78(output) 30 74
Store 81 80 Store 82 81
82:22(HS_CONSTANT_OUT) Load 77(output) 83:22(HS_CONSTANT_OUT) Load 78(output)
ReturnValue 82 ReturnValue 83
FunctionEnd FunctionEnd
...@@ -47,7 +47,7 @@ vertices = 4 ...@@ -47,7 +47,7 @@ vertices = 4
0:? Sequence 0:? Sequence
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 0 (const int) 0:? 0 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -59,7 +59,7 @@ vertices = 4 ...@@ -59,7 +59,7 @@ vertices = 4
0:? 0 (const int) 0:? 0 (const int)
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 1 (const int) 0:? 1 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -103,7 +103,7 @@ vertices = 4 ...@@ -103,7 +103,7 @@ vertices = 4
0:? 'pos' ( in 4-component vector of float Position) 0:? 'pos' ( in 4-component vector of float Position)
0:? 'InvocationId' ( in uint InvocationID) 0:? 'InvocationId' ( in uint InvocationID)
0:? '@patchConstantOutput' (layout( location=1) patch out structure{}) 0:? '@patchConstantOutput' (layout( location=1) patch out structure{})
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
Linked tessellation control stage: Linked tessellation control stage:
...@@ -157,7 +157,7 @@ vertices = 4 ...@@ -157,7 +157,7 @@ vertices = 4
0:? Sequence 0:? Sequence
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 0 (const int) 0:? 0 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -169,7 +169,7 @@ vertices = 4 ...@@ -169,7 +169,7 @@ vertices = 4
0:? 0 (const int) 0:? 0 (const int)
0:? move second child to first child ( temp float) 0:? move second child to first child ( temp float)
0:? direct index ( patch out float TessLevelOuter) 0:? direct index ( patch out float TessLevelOuter)
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
0:? Constant: 0:? Constant:
0:? 1 (const int) 0:? 1 (const int)
0:? direct index ( temp float) 0:? direct index ( temp float)
...@@ -213,16 +213,16 @@ vertices = 4 ...@@ -213,16 +213,16 @@ vertices = 4
0:? 'pos' ( in 4-component vector of float Position) 0:? 'pos' ( in 4-component vector of float Position)
0:? 'InvocationId' ( in uint InvocationID) 0:? 'InvocationId' ( in uint InvocationID)
0:? '@patchConstantOutput' (layout( location=1) patch out structure{}) 0:? '@patchConstantOutput' (layout( location=1) patch out structure{})
0:? '@patchConstantOutput_edges' ( patch out 2-element array of float TessLevelOuter) 0:? '@patchConstantOutput_edges' ( patch out 4-element array of float TessLevelOuter)
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 90 // Id's are bound by 91
Capability Tessellation Capability Tessellation
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationControl 4 "main" 42 45 52 60 62 69 89 EntryPoint TessellationControl 4 "main" 42 45 52 60 62 70 90
ExecutionMode 4 OutputVertices 4 ExecutionMode 4 OutputVertices 4
Name 4 "main" Name 4 "main"
Name 8 "VS_OUT" Name 8 "VS_OUT"
...@@ -247,19 +247,19 @@ vertices = 4 ...@@ -247,19 +247,19 @@ vertices = 4
Name 62 "pos" Name 62 "pos"
Name 63 "param" Name 63 "param"
Name 65 "param" Name 65 "param"
Name 69 "@patchConstantOutput_edges" Name 70 "@patchConstantOutput_edges"
Name 79 "output" Name 80 "output"
Name 87 "HS_CONSTANT_OUT" Name 88 "HS_CONSTANT_OUT"
Name 89 "@patchConstantOutput" Name 90 "@patchConstantOutput"
Decorate 42(ip) Location 0 Decorate 42(ip) Location 0
Decorate 45(@entryPointOutput) Location 0 Decorate 45(@entryPointOutput) Location 0
Decorate 52(InvocationId) BuiltIn InvocationId Decorate 52(InvocationId) BuiltIn InvocationId
Decorate 60(pid) BuiltIn PrimitiveId Decorate 60(pid) BuiltIn PrimitiveId
Decorate 62(pos) BuiltIn Position Decorate 62(pos) BuiltIn Position
Decorate 69(@patchConstantOutput_edges) Patch Decorate 70(@patchConstantOutput_edges) Patch
Decorate 69(@patchConstantOutput_edges) BuiltIn TessLevelOuter Decorate 70(@patchConstantOutput_edges) BuiltIn TessLevelOuter
Decorate 89(@patchConstantOutput) Patch Decorate 90(@patchConstantOutput) Patch
Decorate 89(@patchConstantOutput) Location 1 Decorate 90(@patchConstantOutput) Location 1
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeFloat 32 6: TypeFloat 32
...@@ -295,16 +295,17 @@ vertices = 4 ...@@ -295,16 +295,17 @@ vertices = 4
60(pid): 51(ptr) Variable Input 60(pid): 51(ptr) Variable Input
61: TypePointer Input 19(fvec4) 61: TypePointer Input 19(fvec4)
62(pos): 61(ptr) Variable Input 62(pos): 61(ptr) Variable Input
68: TypePointer Output 22 68: TypeArray 6(float) 10
69(@patchConstantOutput_edges): 68(ptr) Variable Output 69: TypePointer Output 68
70: TypePointer Function 6(float) 70(@patchConstantOutput_edges): 69(ptr) Variable Output
73: TypePointer Output 6(float) 71: TypePointer Function 6(float)
75: 31(int) Constant 1 74: TypePointer Output 6(float)
80: 6(float) Constant 1073741824 76: 31(int) Constant 1
82: 6(float) Constant 1090519040 81: 6(float) Constant 1073741824
87(HS_CONSTANT_OUT): TypeStruct 83: 6(float) Constant 1090519040
88: TypePointer Output 87(HS_CONSTANT_OUT) 88(HS_CONSTANT_OUT): TypeStruct
89(@patchConstantOutput): 88(ptr) Variable Output 89: TypePointer Output 88(HS_CONSTANT_OUT)
90(@patchConstantOutput): 89(ptr) Variable Output
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
40(ip): 12(ptr) Variable Function 40(ip): 12(ptr) Variable Function
...@@ -330,14 +331,14 @@ vertices = 4 ...@@ -330,14 +331,14 @@ vertices = 4
Store 65(param) 66 Store 65(param) 66
67:23(HS_CONSTANT_OUT) FunctionCall 27(PCF(u1;vf4;) 63(param) 65(param) 67:23(HS_CONSTANT_OUT) FunctionCall 27(PCF(u1;vf4;) 63(param) 65(param)
Store 59(@patchConstantResult) 67 Store 59(@patchConstantResult) 67
71: 70(ptr) AccessChain 59(@patchConstantResult) 32 32 72: 71(ptr) AccessChain 59(@patchConstantResult) 32 32
72: 6(float) Load 71 73: 6(float) Load 72
74: 73(ptr) AccessChain 69(@patchConstantOutput_edges) 32 75: 74(ptr) AccessChain 70(@patchConstantOutput_edges) 32
Store 74 72 Store 75 73
76: 70(ptr) AccessChain 59(@patchConstantResult) 32 75 77: 71(ptr) AccessChain 59(@patchConstantResult) 32 76
77: 6(float) Load 76 78: 6(float) Load 77
78: 73(ptr) AccessChain 69(@patchConstantOutput_edges) 75 79: 74(ptr) AccessChain 70(@patchConstantOutput_edges) 76
Store 78 77 Store 79 78
Branch 57 Branch 57
57: Label 57: Label
Return Return
...@@ -357,11 +358,11 @@ vertices = 4 ...@@ -357,11 +358,11 @@ vertices = 4
25(pid): 18(ptr) FunctionParameter 25(pid): 18(ptr) FunctionParameter
26(pos): 20(ptr) FunctionParameter 26(pos): 20(ptr) FunctionParameter
28: Label 28: Label
79(output): 58(ptr) Variable Function 80(output): 58(ptr) Variable Function
81: 70(ptr) AccessChain 79(output) 32 32 82: 71(ptr) AccessChain 80(output) 32 32
Store 81 80 Store 82 81
83: 70(ptr) AccessChain 79(output) 32 75 84: 71(ptr) AccessChain 80(output) 32 76
Store 83 82 Store 84 83
84:23(HS_CONSTANT_OUT) Load 79(output) 85:23(HS_CONSTANT_OUT) Load 80(output)
ReturnValue 84 ReturnValue 85
FunctionEnd FunctionEnd
...@@ -9,8 +9,8 @@ struct hs_in_t ...@@ -9,8 +9,8 @@ struct hs_in_t
struct hs_pcf_t struct hs_pcf_t
{ {
float tfactor[3] : SV_TessFactor; float tfactor[3] : SV_TessFactor; // must turn into a size 4 array in SPIR-V
float flInFactor : SV_InsideTessFactor; float flInFactor : SV_InsideTessFactor; // must turn into a size 2 array in SPIR-V
}; };
struct hs_out_t struct hs_out_t
......
...@@ -1047,6 +1047,8 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru ...@@ -1047,6 +1047,8 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru
if (arraySizes) if (arraySizes)
ioVar->getWritableType().newArraySizes(*arraySizes); ioVar->getWritableType().newArraySizes(*arraySizes);
fixBuiltInArrayType(ioVar->getWritableType());
interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar; interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar;
// Merge qualifier from the user structure // Merge qualifier from the user structure
...@@ -1381,6 +1383,34 @@ void HlslParseContext::trackLinkage(TSymbol& symbol) ...@@ -1381,6 +1383,34 @@ 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
void HlslParseContext::fixBuiltInArrayType(TType& type)
{
int requiredSize = 0;
switch (type.getQualifier().builtIn) {
case EbvTessLevelOuter: requiredSize = 4; break;
case EbvTessLevelInner: requiredSize = 2; break;
case EbvClipDistance: // TODO: ...
case EbvCullDistance: // TODO: ...
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);
}
}
// Variables that correspond to the user-interface in and out of a stage // Variables that correspond to the user-interface in and out of a stage
// (not the built-in interface) are assigned locations and // (not the built-in interface) are assigned locations and
// registered as a linkage node (part of the stage's external interface). // registered as a linkage node (part of the stage's external interface).
...@@ -2031,7 +2061,11 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -2031,7 +2061,11 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
const bool split = isLeft ? isSplitLeft : isSplitRight; const bool split = isLeft ? isSplitLeft : isSplitRight;
const TIntermTyped* outer = isLeft ? outerLeft : outerRight; const TIntermTyped* outer = isLeft ? outerLeft : outerRight;
const TVector<TVariable*>& flatVariables = isLeft ? *leftVariables : *rightVariables; const TVector<TVariable*>& flatVariables = isLeft ? *leftVariables : *rightVariables;
const TOperator op = node->getType().isArray() ? EOpIndexDirect : EOpIndexDirectStruct;
// Index operator if it's an aggregate, else EOpNull
const TOperator op = node->getType().isArray() ? EOpIndexDirect :
node->getType().isStruct() ? EOpIndexDirectStruct : EOpNull;
const TType derefType(node->getType(), member); const TType derefType(node->getType(), member);
if (split && derefType.isBuiltInInterstageIO(language)) { if (split && derefType.isBuiltInInterstageIO(language)) {
...@@ -2047,10 +2081,14 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -2047,10 +2081,14 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
} else if (flattened && isFinalFlattening(derefType)) { } else if (flattened && isFinalFlattening(derefType)) {
subTree = intermediate.addSymbol(*flatVariables[memberIdx++]); subTree = intermediate.addSymbol(*flatVariables[memberIdx++]);
} else { } else {
const TType splitDerefType(splitNode->getType(), splitMember); if (op == EOpNull) {
subTree = splitNode;
} else {
const TType splitDerefType(splitNode->getType(), splitMember);
subTree = intermediate.addIndex(op, splitNode, intermediate.addConstantUnion(splitMember, loc), loc); subTree = intermediate.addIndex(op, splitNode, intermediate.addConstantUnion(splitMember, loc), loc);
subTree->setType(splitDerefType); subTree->setType(splitDerefType);
}
} }
return subTree; return subTree;
...@@ -2069,11 +2107,15 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -2069,11 +2107,15 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
// If we get here, we are assigning to or from a whole array or struct that must be // If we get here, we are assigning to or from a whole array or struct that must be
// flattened, so have to do member-by-member assignment: // flattened, so have to do member-by-member assignment:
if (left->getType().isArray()) { if (left->getType().isArray() || right->getType().isArray()) {
const TType dereferencedType(left->getType(), 0); const int elementsL = left->getType().isArray() ? left->getType().getOuterArraySize() : 1;
const int elementsR = right->getType().isArray() ? right->getType().getOuterArraySize() : 1;
// The arrays may not be the same size, e.g, if the size has been forced for EbvTessLevelInner or Outer.
const int elementsToCopy = std::min(elementsL, elementsR);
// array case // array case
for (int element=0; element < left->getType().getOuterArraySize(); ++element) { for (int element=0; element < elementsToCopy; ++element) {
arrayElement.push_back(element); arrayElement.push_back(element);
// Add a new AST symbol node if we have a temp variable holding a complex RHS. // Add a new AST symbol node if we have a temp variable holding a complex RHS.
...@@ -2083,10 +2125,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -2083,10 +2125,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left, element, splitLeft, element) : subLeft; TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left, element, splitLeft, element) : subLeft;
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right, element, splitRight, element) : subRight; TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right, element, splitRight, element) : subRight;
if (isFinalFlattening(dereferencedType)) traverse(subLeft, subRight, subSplitLeft, subSplitRight);
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
else
traverse(subLeft, subRight, subSplitLeft, subSplitRight);
arrayElement.pop_back(); arrayElement.pop_back();
} }
...@@ -2120,8 +2159,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -2120,8 +2159,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
// subtree here IFF it does not itself contain any interstage built-in IO variables, so we only have to // subtree here IFF it does not itself contain any interstage built-in IO variables, so we only have to
// recurse into it if there's something for splitting to do. That can save a lot of AST verbosity for // recurse into it if there's something for splitting to do. That can save a lot of AST verbosity for
// a bunch of memberwise copies. // a bunch of memberwise copies.
if (isFinalFlattening(typeL) || (!isFlattenLeft && !isFlattenRight && if ((!isFlattenLeft && !isFlattenRight &&
!typeL.containsBuiltInInterstageIO(language) && !typeR.containsBuiltInInterstageIO(language))) { !typeL.containsBuiltInInterstageIO(language) && !typeR.containsBuiltInInterstageIO(language))) {
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subSplitLeft, subSplitRight, loc), loc); assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subSplitLeft, subSplitRight, loc), loc);
} else { } else {
traverse(subLeft, subRight, subSplitLeft, subSplitRight); traverse(subLeft, subRight, subSplitLeft, subSplitRight);
...@@ -2131,8 +2170,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -2131,8 +2170,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
memberR += (typeR.isBuiltInInterstageIO(language) ? 0 : 1); memberR += (typeR.isBuiltInInterstageIO(language) ? 0 : 1);
} }
} else { } else {
assert(0); // we should never be called on a non-flattenable thing, because // Member copy
// that case bails out above to a simple copy. assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, right, loc), loc);
} }
}; };
......
...@@ -248,6 +248,8 @@ protected: ...@@ -248,6 +248,8 @@ protected:
void addInterstageIoToLinkage(); void addInterstageIoToLinkage();
void addPatchConstantInvocation(); void addPatchConstantInvocation();
void fixBuiltInArrayType(TType&);
void flatten(const TSourceLoc& loc, const TVariable& variable); void flatten(const TSourceLoc& loc, const TVariable& variable);
int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name); int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
int flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name); int flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment