зеркало из https://github.com/stride3d/xkslang.git
Fix #980: flatten opaque initializers to use aliases.
This commit is contained in:
Родитель
37c202aa02
Коммит
0e6e2ffd9c
|
@ -0,0 +1,132 @@
|
||||||
|
hlsl.flattenOpaqueInit.vert
|
||||||
|
Shader version: 500
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Function Definition: lookUp(struct-FxaaTex-p1-t211; ( temp 4-component vector of float)
|
||||||
|
0:5 Function Parameters:
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? Sequence
|
||||||
|
0:6 Branch: Return with expression
|
||||||
|
0:6 texture ( temp 4-component vector of float)
|
||||||
|
0:6 Construct combined texture-sampler ( temp sampler2D)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 0.300000
|
||||||
|
0:? 0.400000
|
||||||
|
0:10 Function Definition: @main( ( temp 4-component vector of float)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:12 Branch: Return with expression
|
||||||
|
0:12 Function Call: lookUp(struct-FxaaTex-p1-t211; ( temp 4-component vector of float)
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:10 Function Definition: main( ( temp void)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:10 move second child to first child ( temp 4-component vector of float)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
0:10 Function Call: @main( ( temp 4-component vector of float)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
|
||||||
|
|
||||||
|
Linked vertex stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 500
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Function Definition: lookUp(struct-FxaaTex-p1-t211; ( temp 4-component vector of float)
|
||||||
|
0:5 Function Parameters:
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? Sequence
|
||||||
|
0:6 Branch: Return with expression
|
||||||
|
0:6 texture ( temp 4-component vector of float)
|
||||||
|
0:6 Construct combined texture-sampler ( temp sampler2D)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 0.300000
|
||||||
|
0:? 0.400000
|
||||||
|
0:10 Function Definition: @main( ( temp 4-component vector of float)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:12 Branch: Return with expression
|
||||||
|
0:12 Function Call: lookUp(struct-FxaaTex-p1-t211; ( temp 4-component vector of float)
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:10 Function Definition: main( ( temp void)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:10 move second child to first child ( temp 4-component vector of float)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
0:10 Function Call: @main( ( temp 4-component vector of float)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 40
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Vertex 4 "main" 38
|
||||||
|
Source HLSL 500
|
||||||
|
Name 4 "main"
|
||||||
|
Name 15 "lookUp(struct-FxaaTex-p1-t211;"
|
||||||
|
Name 13 "smpl"
|
||||||
|
Name 14 "tex"
|
||||||
|
Name 18 "@main("
|
||||||
|
Name 32 "g_tInputTexture_sampler"
|
||||||
|
Name 33 "g_tInputTexture"
|
||||||
|
Name 38 "@entryPointOutput"
|
||||||
|
Decorate 32(g_tInputTexture_sampler) DescriptorSet 0
|
||||||
|
Decorate 33(g_tInputTexture) DescriptorSet 0
|
||||||
|
Decorate 38(@entryPointOutput) Location 0
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeSampler
|
||||||
|
7: TypePointer UniformConstant 6
|
||||||
|
8: TypeFloat 32
|
||||||
|
9: TypeImage 8(float) 2D sampled format:Unknown
|
||||||
|
10: TypePointer UniformConstant 9
|
||||||
|
11: TypeVector 8(float) 4
|
||||||
|
12: TypeFunction 11(fvec4) 7(ptr) 10(ptr)
|
||||||
|
17: TypeFunction 11(fvec4)
|
||||||
|
22: TypeSampledImage 9
|
||||||
|
24: TypeVector 8(float) 2
|
||||||
|
25: 8(float) Constant 1050253722
|
||||||
|
26: 8(float) Constant 1053609165
|
||||||
|
27: 24(fvec2) ConstantComposite 25 26
|
||||||
|
28: 8(float) Constant 0
|
||||||
|
32(g_tInputTexture_sampler): 7(ptr) Variable UniformConstant
|
||||||
|
33(g_tInputTexture): 10(ptr) Variable UniformConstant
|
||||||
|
37: TypePointer Output 11(fvec4)
|
||||||
|
38(@entryPointOutput): 37(ptr) Variable Output
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
39: 11(fvec4) FunctionCall 18(@main()
|
||||||
|
Store 38(@entryPointOutput) 39
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
15(lookUp(struct-FxaaTex-p1-t211;): 11(fvec4) Function None 12
|
||||||
|
13(smpl): 7(ptr) FunctionParameter
|
||||||
|
14(tex): 10(ptr) FunctionParameter
|
||||||
|
16: Label
|
||||||
|
20: 9 Load 14(tex)
|
||||||
|
21: 6 Load 13(smpl)
|
||||||
|
23: 22 SampledImage 20 21
|
||||||
|
29: 11(fvec4) ImageSampleExplicitLod 23 27 Lod 28
|
||||||
|
ReturnValue 29
|
||||||
|
FunctionEnd
|
||||||
|
18(@main(): 11(fvec4) Function None 17
|
||||||
|
19: Label
|
||||||
|
34: 11(fvec4) FunctionCall 15(lookUp(struct-FxaaTex-p1-t211;) 32(g_tInputTexture_sampler) 33(g_tInputTexture)
|
||||||
|
ReturnValue 34
|
||||||
|
FunctionEnd
|
|
@ -0,0 +1,159 @@
|
||||||
|
hlsl.flattenOpaqueInitMix.vert
|
||||||
|
Shader version: 500
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Function Definition: lookUp(struct-FxaaTex-p1-t21-f11; ( temp 4-component vector of float)
|
||||||
|
0:5 Function Parameters:
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? 'f' ( in float)
|
||||||
|
0:? Sequence
|
||||||
|
0:6 Branch: Return with expression
|
||||||
|
0:6 texture ( temp 4-component vector of float)
|
||||||
|
0:6 Construct combined texture-sampler ( temp sampler2D)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? Construct vec2 ( temp 2-component vector of float)
|
||||||
|
0:? 'f' ( in float)
|
||||||
|
0:? 'f' ( in float)
|
||||||
|
0:10 Function Definition: @main( ( temp 4-component vector of float)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:11 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:11 move second child to first child ( temp float)
|
||||||
|
0:? 'f' ( temp float)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 0.500000
|
||||||
|
0:12 Branch: Return with expression
|
||||||
|
0:12 Function Call: lookUp(struct-FxaaTex-p1-t21-f11; ( temp 4-component vector of float)
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:? 'f' ( temp float)
|
||||||
|
0:10 Function Definition: main( ( temp void)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:10 move second child to first child ( temp 4-component vector of float)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
0:10 Function Call: @main( ( temp 4-component vector of float)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
|
||||||
|
|
||||||
|
Linked vertex stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 500
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Function Definition: lookUp(struct-FxaaTex-p1-t21-f11; ( temp 4-component vector of float)
|
||||||
|
0:5 Function Parameters:
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? 'f' ( in float)
|
||||||
|
0:? Sequence
|
||||||
|
0:6 Branch: Return with expression
|
||||||
|
0:6 texture ( temp 4-component vector of float)
|
||||||
|
0:6 Construct combined texture-sampler ( temp sampler2D)
|
||||||
|
0:? 'tex' ( in texture2D)
|
||||||
|
0:? 'smpl' ( in sampler)
|
||||||
|
0:? Construct vec2 ( temp 2-component vector of float)
|
||||||
|
0:? 'f' ( in float)
|
||||||
|
0:? 'f' ( in float)
|
||||||
|
0:10 Function Definition: @main( ( temp 4-component vector of float)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:11 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:11 move second child to first child ( temp float)
|
||||||
|
0:? 'f' ( temp float)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 0.500000
|
||||||
|
0:12 Branch: Return with expression
|
||||||
|
0:12 Function Call: lookUp(struct-FxaaTex-p1-t21-f11; ( temp 4-component vector of float)
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:? 'f' ( temp float)
|
||||||
|
0:10 Function Definition: main( ( temp void)
|
||||||
|
0:10 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:10 move second child to first child ( temp 4-component vector of float)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
0:10 Function Call: @main( ( temp 4-component vector of float)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'g_tInputTexture_sampler' ( uniform sampler)
|
||||||
|
0:? 'g_tInputTexture' ( uniform texture2D)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 46
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Vertex 4 "main" 44
|
||||||
|
Source HLSL 500
|
||||||
|
Name 4 "main"
|
||||||
|
Name 17 "lookUp(struct-FxaaTex-p1-t21-f11;"
|
||||||
|
Name 14 "smpl"
|
||||||
|
Name 15 "tex"
|
||||||
|
Name 16 "f"
|
||||||
|
Name 20 "@main("
|
||||||
|
Name 34 "f"
|
||||||
|
Name 36 "g_tInputTexture_sampler"
|
||||||
|
Name 37 "g_tInputTexture"
|
||||||
|
Name 38 "param"
|
||||||
|
Name 44 "@entryPointOutput"
|
||||||
|
Decorate 36(g_tInputTexture_sampler) DescriptorSet 0
|
||||||
|
Decorate 37(g_tInputTexture) DescriptorSet 0
|
||||||
|
Decorate 44(@entryPointOutput) Location 0
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeSampler
|
||||||
|
7: TypePointer UniformConstant 6
|
||||||
|
8: TypeFloat 32
|
||||||
|
9: TypeImage 8(float) 2D sampled format:Unknown
|
||||||
|
10: TypePointer UniformConstant 9
|
||||||
|
11: TypePointer Function 8(float)
|
||||||
|
12: TypeVector 8(float) 4
|
||||||
|
13: TypeFunction 12(fvec4) 7(ptr) 10(ptr) 11(ptr)
|
||||||
|
19: TypeFunction 12(fvec4)
|
||||||
|
24: TypeSampledImage 9
|
||||||
|
28: TypeVector 8(float) 2
|
||||||
|
30: 8(float) Constant 0
|
||||||
|
35: 8(float) Constant 1056964608
|
||||||
|
36(g_tInputTexture_sampler): 7(ptr) Variable UniformConstant
|
||||||
|
37(g_tInputTexture): 10(ptr) Variable UniformConstant
|
||||||
|
43: TypePointer Output 12(fvec4)
|
||||||
|
44(@entryPointOutput): 43(ptr) Variable Output
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
45: 12(fvec4) FunctionCall 20(@main()
|
||||||
|
Store 44(@entryPointOutput) 45
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
17(lookUp(struct-FxaaTex-p1-t21-f11;): 12(fvec4) Function None 13
|
||||||
|
14(smpl): 7(ptr) FunctionParameter
|
||||||
|
15(tex): 10(ptr) FunctionParameter
|
||||||
|
16(f): 11(ptr) FunctionParameter
|
||||||
|
18: Label
|
||||||
|
22: 9 Load 15(tex)
|
||||||
|
23: 6 Load 14(smpl)
|
||||||
|
25: 24 SampledImage 22 23
|
||||||
|
26: 8(float) Load 16(f)
|
||||||
|
27: 8(float) Load 16(f)
|
||||||
|
29: 28(fvec2) CompositeConstruct 26 27
|
||||||
|
31: 12(fvec4) ImageSampleExplicitLod 25 29 Lod 30
|
||||||
|
ReturnValue 31
|
||||||
|
FunctionEnd
|
||||||
|
20(@main(): 12(fvec4) Function None 19
|
||||||
|
21: Label
|
||||||
|
34(f): 11(ptr) Variable Function
|
||||||
|
38(param): 11(ptr) Variable Function
|
||||||
|
Store 34(f) 35
|
||||||
|
39: 8(float) Load 34(f)
|
||||||
|
Store 38(param) 39
|
||||||
|
40: 12(fvec4) FunctionCall 17(lookUp(struct-FxaaTex-p1-t21-f11;) 36(g_tInputTexture_sampler) 37(g_tInputTexture) 38(param)
|
||||||
|
ReturnValue 40
|
||||||
|
FunctionEnd
|
|
@ -0,0 +1,13 @@
|
||||||
|
struct FxaaTex { SamplerState smpl; Texture2D tex; };
|
||||||
|
SamplerState g_tInputTexture_sampler; Texture2D g_tInputTexture;
|
||||||
|
|
||||||
|
float4 lookUp(FxaaTex tex)
|
||||||
|
{
|
||||||
|
return tex.tex.Sample(tex.smpl, float2(0.3, 0.4));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main() : SV_TARGET0
|
||||||
|
{
|
||||||
|
FxaaTex tex = { g_tInputTexture_sampler, g_tInputTexture };
|
||||||
|
return lookUp(tex);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
struct FxaaTex { SamplerState smpl; Texture2D tex; float f; };
|
||||||
|
SamplerState g_tInputTexture_sampler; Texture2D g_tInputTexture;
|
||||||
|
|
||||||
|
float4 lookUp(FxaaTex tex)
|
||||||
|
{
|
||||||
|
return tex.tex.Sample(tex.smpl, float2(tex.f, tex.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main() : SV_TARGET0
|
||||||
|
{
|
||||||
|
FxaaTex tex = { g_tInputTexture_sampler, g_tInputTexture, 0.5 };
|
||||||
|
return lookUp(tex);
|
||||||
|
}
|
|
@ -122,6 +122,8 @@ INSTANTIATE_TEST_CASE_P(
|
||||||
{"hlsl.float4.frag", "PixelShaderFunction"},
|
{"hlsl.float4.frag", "PixelShaderFunction"},
|
||||||
{"hlsl.flatten.return.frag", "main"},
|
{"hlsl.flatten.return.frag", "main"},
|
||||||
{"hlsl.flattenOpaque.frag", "main"},
|
{"hlsl.flattenOpaque.frag", "main"},
|
||||||
|
{"hlsl.flattenOpaqueInit.vert", "main"},
|
||||||
|
{"hlsl.flattenOpaqueInitMix.vert", "main"},
|
||||||
{"hlsl.forLoop.frag", "PixelShaderFunction"},
|
{"hlsl.forLoop.frag", "PixelShaderFunction"},
|
||||||
{"hlsl.gather.array.dx10.frag", "main"},
|
{"hlsl.gather.array.dx10.frag", "main"},
|
||||||
{"hlsl.gather.basic.dx10.frag", "main"},
|
{"hlsl.gather.basic.dx10.frag", "main"},
|
||||||
|
|
|
@ -506,12 +506,14 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with sampler aliasing: turning assignments into aliases
|
// Deal with sampler aliasing: turning assignments into aliases
|
||||||
|
// Return a placeholder node for higher-level code that think assignments must
|
||||||
|
// generate code.
|
||||||
TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const char* op, TIntermTyped*& node)
|
TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const char* op, TIntermTyped*& node)
|
||||||
{
|
{
|
||||||
// Can only alias an assignment: "s1 = s2"
|
// Can only alias an assignment: "s1 = s2"
|
||||||
TIntermBinary* binary = node->getAsBinaryNode();
|
TIntermBinary* binary = node->getAsBinaryNode();
|
||||||
if (binary == nullptr || node->getAsOperator()->getOp() != EOpAssign ||
|
if (binary == nullptr || node->getAsOperator()->getOp() != EOpAssign ||
|
||||||
binary->getLeft() ->getAsSymbolNode() == nullptr ||
|
binary->getLeft()->getAsSymbolNode() == nullptr ||
|
||||||
binary->getRight()->getAsSymbolNode() == nullptr) {
|
binary->getRight()->getAsSymbolNode() == nullptr) {
|
||||||
error(loc, "can't modify sampler", op, "");
|
error(loc, "can't modify sampler", op, "");
|
||||||
return node;
|
return node;
|
||||||
|
@ -520,11 +522,25 @@ TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const
|
||||||
if (controlFlowNestingLevel > 0)
|
if (controlFlowNestingLevel > 0)
|
||||||
warn(loc, "sampler or image aliased under control flow; consumption must be in same path", op, "");
|
warn(loc, "sampler or image aliased under control flow; consumption must be in same path", op, "");
|
||||||
|
|
||||||
|
TIntermTyped* set = setOpaqueLvalue(binary->getLeft(), binary->getRight());
|
||||||
|
if (set == nullptr)
|
||||||
|
warn(loc, "could not create alias for sampler", op, "");
|
||||||
|
else
|
||||||
|
node = set;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do an opaque assignment that needs to turn into an alias.
|
||||||
|
// Return nullptr if it can't be done, otherwise return a placeholder
|
||||||
|
// node for higher-level code that think assignments must generate code.
|
||||||
|
TIntermTyped* HlslParseContext::setOpaqueLvalue(TIntermTyped* leftTyped, TIntermTyped* rightTyped)
|
||||||
|
{
|
||||||
// Best is if we are aliasing a flattened struct member "S.s1 = s2",
|
// Best is if we are aliasing a flattened struct member "S.s1 = s2",
|
||||||
// in which case we want to update the flattening information with the alias,
|
// in which case we want to update the flattening information with the alias,
|
||||||
// making everything else work seamlessly.
|
// making everything else work seamlessly.
|
||||||
TIntermSymbol* left = binary->getLeft()->getAsSymbolNode();
|
TIntermSymbol* left = leftTyped->getAsSymbolNode();
|
||||||
TIntermSymbol* right = binary->getRight()->getAsSymbolNode();
|
TIntermSymbol* right = rightTyped->getAsSymbolNode();
|
||||||
for (auto fit = flattenMap.begin(); fit != flattenMap.end(); ++fit) {
|
for (auto fit = flattenMap.begin(); fit != flattenMap.end(); ++fit) {
|
||||||
for (auto mit = fit->second.members.begin(); mit != fit->second.members.end(); ++mit) {
|
for (auto mit = fit->second.members.begin(); mit != fit->second.members.end(); ++mit) {
|
||||||
if ((*mit)->getUniqueId() == left->getId()) {
|
if ((*mit)->getUniqueId() == left->getId()) {
|
||||||
|
@ -533,15 +549,12 @@ TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const
|
||||||
(*mit)->setUniqueId(right->getId());
|
(*mit)->setUniqueId(right->getId());
|
||||||
// replace node (rest of compiler expects either an error or code to generate)
|
// replace node (rest of compiler expects either an error or code to generate)
|
||||||
// with pointless access
|
// with pointless access
|
||||||
node = binary->getRight();
|
return right;
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
warn(loc, "could not create alias for sampler", op, "");
|
return nullptr;
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
|
void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
|
||||||
|
@ -2412,6 +2425,34 @@ TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc
|
||||||
return assignList;
|
return assignList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For a declaration with an initializer, where the initialized symbol is flattened,
|
||||||
|
// and possibly contains opaque values, such that the initializer should never exist
|
||||||
|
// as emitted code, because even creating the initializer would write opaques.
|
||||||
|
//
|
||||||
|
// Decompose this into individual member-wise assignments, which themselves are
|
||||||
|
// expected to then not exist for opaque types, because they will turn into aliases.
|
||||||
|
//
|
||||||
|
// Return a node that contains the non-aliased assignments that must continue to exist.
|
||||||
|
TIntermAggregate* HlslParseContext::flattenedInit(const TSourceLoc& loc, TIntermSymbol* symbol, const TIntermAggregate& initializer)
|
||||||
|
{
|
||||||
|
TIntermAggregate* initList = nullptr;
|
||||||
|
// synthesize an access to each member, and then an assignment to it
|
||||||
|
const TTypeList& typeList = *symbol->getType().getStruct();
|
||||||
|
for (int member = 0; member < (int)typeList.size(); ++member) {
|
||||||
|
TIntermTyped* memberInitializer = initializer.getSequence()[member]->getAsTyped();
|
||||||
|
TIntermTyped* flattenedMember = flattenAccess(symbol, member);
|
||||||
|
if (flattenedMember->getType().containsOpaque())
|
||||||
|
setOpaqueLvalue(flattenedMember, memberInitializer);
|
||||||
|
else
|
||||||
|
initList = intermediate.growAggregate(initList, handleAssign(loc, EOpAssign, flattenedMember,
|
||||||
|
memberInitializer));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initList)
|
||||||
|
initList->setOperator(EOpSequence);
|
||||||
|
return initList;
|
||||||
|
}
|
||||||
|
|
||||||
// Some simple source assignments need to be flattened to a sequence
|
// Some simple source assignments need to be flattened to a sequence
|
||||||
// of AST assignments. Catch these and flatten, otherwise, pass through
|
// of AST assignments. Catch these and flatten, otherwise, pass through
|
||||||
// to intermediate.addAssign().
|
// to intermediate.addAssign().
|
||||||
|
@ -2449,7 +2490,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
|
||||||
|
|
||||||
// A temporary to store the right node's value, so we don't keep indirecting into it
|
// A temporary to store the right node's value, so we don't keep indirecting into it
|
||||||
// if it's not a simple symbol.
|
// if it's not a simple symbol.
|
||||||
TVariable* rhsTempVar = nullptr;
|
TVariable* rhsTempVar = nullptr;
|
||||||
|
|
||||||
// If the RHS is a simple symbol node, we'll copy it for each member.
|
// If the RHS is a simple symbol node, we'll copy it for each member.
|
||||||
TIntermSymbol* cloneSymNode = nullptr;
|
TIntermSymbol* cloneSymNode = nullptr;
|
||||||
|
@ -7222,27 +7263,22 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, const TStr
|
||||||
error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
|
error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flattenVar)
|
|
||||||
flatten(loc, *symbol->getAsVariable());
|
|
||||||
|
|
||||||
if (symbol == nullptr)
|
if (symbol == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
if (flattenVar)
|
||||||
|
flatten(loc, *symbol->getAsVariable());
|
||||||
|
|
||||||
|
if (initializer == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// Deal with initializer
|
// Deal with initializer
|
||||||
TIntermNode* initNode = nullptr;
|
TVariable* variable = symbol->getAsVariable();
|
||||||
if (symbol && initializer) {
|
if (variable == nullptr) {
|
||||||
if (flattenVar)
|
error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
|
||||||
error(loc, "flattened array with initializer list unsupported", identifier.c_str(), "");
|
return nullptr;
|
||||||
|
|
||||||
TVariable* variable = symbol->getAsVariable();
|
|
||||||
if (variable == nullptr) {
|
|
||||||
error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
initNode = executeInitializer(loc, initializer, variable);
|
|
||||||
}
|
}
|
||||||
|
return executeInitializer(loc, initializer, variable, flattenVar);
|
||||||
return initNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick up global defaults from the provide global defaults into dst.
|
// Pick up global defaults from the provide global defaults into dst.
|
||||||
|
@ -7308,7 +7344,7 @@ TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, const TStrin
|
||||||
// Returning nullptr just means there is no code to execute to handle the
|
// Returning nullptr just means there is no code to execute to handle the
|
||||||
// initializer, which will, for example, be the case for constant initializers.
|
// initializer, which will, for example, be the case for constant initializers.
|
||||||
//
|
//
|
||||||
TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
|
TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable, bool flattened)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Identifier must be of type constant, a global, or a temporary, and
|
// Identifier must be of type constant, a global, or a temporary, and
|
||||||
|
@ -7329,6 +7365,7 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
|
||||||
TType skeletalType;
|
TType skeletalType;
|
||||||
skeletalType.shallowCopy(variable->getType());
|
skeletalType.shallowCopy(variable->getType());
|
||||||
skeletalType.getQualifier().makeTemporary();
|
skeletalType.getQualifier().makeTemporary();
|
||||||
|
TIntermAggregate* initializerList = nullptr;
|
||||||
if (initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull)
|
if (initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull)
|
||||||
initializer = convertInitializerList(loc, skeletalType, initializer, nullptr);
|
initializer = convertInitializerList(loc, skeletalType, initializer, nullptr);
|
||||||
if (initializer == nullptr) {
|
if (initializer == nullptr) {
|
||||||
|
@ -7388,11 +7425,20 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
|
||||||
// normal assigning of a value to a variable...
|
// normal assigning of a value to a variable...
|
||||||
specializationCheck(loc, initializer->getType(), "initializer");
|
specializationCheck(loc, initializer->getType(), "initializer");
|
||||||
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||||
TIntermNode* initNode = handleAssign(loc, EOpAssign, intermSymbol, initializer);
|
|
||||||
if (initNode == nullptr)
|
|
||||||
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
|
||||||
|
|
||||||
return initNode;
|
// If we are flattening, it could be due to setting opaques, which must be handled
|
||||||
|
// as aliases, and the 'initializer' node cannot actually be emitted, because it
|
||||||
|
// itself stores the result of the constructor, and we can't store to opaques.
|
||||||
|
// handleAssign() will emit the initializer.
|
||||||
|
TIntermNode* initNode = nullptr;
|
||||||
|
if (flattened && intermSymbol->getType().containsOpaque())
|
||||||
|
return flattenedInit(loc, intermSymbol, *initializer->getAsAggregate());
|
||||||
|
else {
|
||||||
|
initNode = handleAssign(loc, EOpAssign, intermSymbol, initializer);
|
||||||
|
if (initNode == nullptr)
|
||||||
|
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
||||||
|
return initNode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -87,6 +87,7 @@ public:
|
||||||
void remapNonEntryPointIO(TFunction& function);
|
void remapNonEntryPointIO(TFunction& function);
|
||||||
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
|
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
|
||||||
void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
|
void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
|
||||||
|
TIntermAggregate* flattenedInit(const TSourceLoc&, TIntermSymbol*, const TIntermAggregate&);
|
||||||
TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
|
TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
|
||||||
TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
|
TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
|
||||||
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*);
|
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*);
|
||||||
|
@ -191,6 +192,7 @@ public:
|
||||||
// Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore.
|
// Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore.
|
||||||
TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node);
|
TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node);
|
||||||
TIntermTyped* handleSamplerLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node);
|
TIntermTyped* handleSamplerLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node);
|
||||||
|
TIntermTyped* setOpaqueLvalue(TIntermTyped* left, TIntermTyped* right);
|
||||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||||
|
|
||||||
TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&);
|
TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&);
|
||||||
|
@ -231,7 +233,7 @@ protected:
|
||||||
TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const;
|
TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const;
|
||||||
TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track);
|
TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track);
|
||||||
void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track);
|
void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track);
|
||||||
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
|
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable, bool flattened);
|
||||||
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit);
|
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit);
|
||||||
bool isScalarConstructor(const TIntermNode*);
|
bool isScalarConstructor(const TIntermNode*);
|
||||||
TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
|
TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче