From 4329d555adbbd9dadfa33e8dd2b93ea5e914abe0 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 21 Jun 2017 01:35:57 -0600 Subject: [PATCH] HLSL: Broaden solution for #940, editing integer input for 'flat'. --- .../hlsl.intrinsics.double.frag.out | 54 ++++--- Test/baseResults/hlsl.struct.frag.out | 9 +- .../baseResults/hlsl.synthesizeInput.frag.out | 151 ++++++++++++++++++ Test/hlsl.synthesizeInput.frag | 9 ++ gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslParseHelper.cpp | 71 +++++--- 6 files changed, 249 insertions(+), 46 deletions(-) create mode 100755 Test/baseResults/hlsl.synthesizeInput.frag.out create mode 100644 Test/hlsl.synthesizeInput.frag diff --git a/Test/baseResults/hlsl.intrinsics.double.frag.out b/Test/baseResults/hlsl.intrinsics.double.frag.out index 3f340813..020817a5 100644 --- a/Test/baseResults/hlsl.intrinsics.double.frag.out +++ b/Test/baseResults/hlsl.intrinsics.double.frag.out @@ -35,22 +35,22 @@ gl_FragCoord origin is upper left 0:? Sequence 0:5 move second child to first child ( temp double) 0:? 'inDV1a' ( temp double) -0:? 'inDV1a' (layout( location=0) in double) +0:? 'inDV1a' (layout( location=0) flat in double) 0:5 move second child to first child ( temp double) 0:? 'inDV1b' ( temp double) -0:? 'inDV1b' (layout( location=1) in double) +0:? 'inDV1b' (layout( location=1) flat in double) 0:5 move second child to first child ( temp double) 0:? 'inDV1c' ( temp double) -0:? 'inDV1c' (layout( location=2) in double) +0:? 'inDV1c' (layout( location=2) flat in double) 0:5 move second child to first child ( temp 2-component vector of double) 0:? 'inDV2' ( temp 2-component vector of double) -0:? 'inDV2' (layout( location=3) in 2-component vector of double) +0:? 'inDV2' (layout( location=3) flat in 2-component vector of double) 0:5 move second child to first child ( temp 3-component vector of double) 0:? 'inDV3' ( temp 3-component vector of double) -0:? 'inDV3' (layout( location=4) in 3-component vector of double) +0:? 'inDV3' (layout( location=4) flat in 3-component vector of double) 0:5 move second child to first child ( temp 4-component vector of double) 0:? 'inDV4' ( temp 4-component vector of double) -0:? 'inDV4' (layout( location=6) in 4-component vector of double) +0:? 'inDV4' (layout( location=6) flat in 4-component vector of double) 0:5 move second child to first child ( temp uint) 0:? 'inU1a' ( temp uint) 0:? 'inU1a' (layout( location=8) flat in uint) @@ -70,12 +70,12 @@ gl_FragCoord origin is upper left 0:? 'inU1b' ( temp uint) 0:? Linker Objects 0:? '@entryPointOutput' (layout( location=0) out float) -0:? 'inDV1a' (layout( location=0) in double) -0:? 'inDV1b' (layout( location=1) in double) -0:? 'inDV1c' (layout( location=2) in double) -0:? 'inDV2' (layout( location=3) in 2-component vector of double) -0:? 'inDV3' (layout( location=4) in 3-component vector of double) -0:? 'inDV4' (layout( location=6) in 4-component vector of double) +0:? 'inDV1a' (layout( location=0) flat in double) +0:? 'inDV1b' (layout( location=1) flat in double) +0:? 'inDV1c' (layout( location=2) flat in double) +0:? 'inDV2' (layout( location=3) flat in 2-component vector of double) +0:? 'inDV3' (layout( location=4) flat in 3-component vector of double) +0:? 'inDV4' (layout( location=6) flat in 4-component vector of double) 0:? 'inU1a' (layout( location=8) flat in uint) 0:? 'inU1b' (layout( location=9) flat in uint) @@ -119,22 +119,22 @@ gl_FragCoord origin is upper left 0:? Sequence 0:5 move second child to first child ( temp double) 0:? 'inDV1a' ( temp double) -0:? 'inDV1a' (layout( location=0) in double) +0:? 'inDV1a' (layout( location=0) flat in double) 0:5 move second child to first child ( temp double) 0:? 'inDV1b' ( temp double) -0:? 'inDV1b' (layout( location=1) in double) +0:? 'inDV1b' (layout( location=1) flat in double) 0:5 move second child to first child ( temp double) 0:? 'inDV1c' ( temp double) -0:? 'inDV1c' (layout( location=2) in double) +0:? 'inDV1c' (layout( location=2) flat in double) 0:5 move second child to first child ( temp 2-component vector of double) 0:? 'inDV2' ( temp 2-component vector of double) -0:? 'inDV2' (layout( location=3) in 2-component vector of double) +0:? 'inDV2' (layout( location=3) flat in 2-component vector of double) 0:5 move second child to first child ( temp 3-component vector of double) 0:? 'inDV3' ( temp 3-component vector of double) -0:? 'inDV3' (layout( location=4) in 3-component vector of double) +0:? 'inDV3' (layout( location=4) flat in 3-component vector of double) 0:5 move second child to first child ( temp 4-component vector of double) 0:? 'inDV4' ( temp 4-component vector of double) -0:? 'inDV4' (layout( location=6) in 4-component vector of double) +0:? 'inDV4' (layout( location=6) flat in 4-component vector of double) 0:5 move second child to first child ( temp uint) 0:? 'inU1a' ( temp uint) 0:? 'inU1a' (layout( location=8) flat in uint) @@ -154,12 +154,12 @@ gl_FragCoord origin is upper left 0:? 'inU1b' ( temp uint) 0:? Linker Objects 0:? '@entryPointOutput' (layout( location=0) out float) -0:? 'inDV1a' (layout( location=0) in double) -0:? 'inDV1b' (layout( location=1) in double) -0:? 'inDV1c' (layout( location=2) in double) -0:? 'inDV2' (layout( location=3) in 2-component vector of double) -0:? 'inDV3' (layout( location=4) in 3-component vector of double) -0:? 'inDV4' (layout( location=6) in 4-component vector of double) +0:? 'inDV1a' (layout( location=0) flat in double) +0:? 'inDV1b' (layout( location=1) flat in double) +0:? 'inDV1c' (layout( location=2) flat in double) +0:? 'inDV2' (layout( location=3) flat in 2-component vector of double) +0:? 'inDV3' (layout( location=4) flat in 3-component vector of double) +0:? 'inDV4' (layout( location=6) flat in 4-component vector of double) 0:? 'inU1a' (layout( location=8) flat in uint) 0:? 'inU1b' (layout( location=9) flat in uint) @@ -211,11 +211,17 @@ gl_FragCoord origin is upper left Name 83 "param" Name 85 "param" Name 87 "param" + Decorate 44(inDV1a) Flat Decorate 44(inDV1a) Location 0 + Decorate 47(inDV1b) Flat Decorate 47(inDV1b) Location 1 + Decorate 50(inDV1c) Flat Decorate 50(inDV1c) Location 2 + Decorate 54(inDV2) Flat Decorate 54(inDV2) Location 3 + Decorate 58(inDV3) Flat Decorate 58(inDV3) Location 4 + Decorate 62(inDV4) Flat Decorate 62(inDV4) Location 6 Decorate 66(inU1a) Flat Decorate 66(inU1a) Location 8 diff --git a/Test/baseResults/hlsl.struct.frag.out b/Test/baseResults/hlsl.struct.frag.out index 5926833f..4501f80a 100755 --- a/Test/baseResults/hlsl.struct.frag.out +++ b/Test/baseResults/hlsl.struct.frag.out @@ -79,7 +79,7 @@ gl_FragCoord origin is upper left 0:? 's' ( temp structure{ temp 4-component vector of float a, temp bool b, temp 1-component vector of float c, temp 2-component vector of float d, temp bool ff1, temp bool ff2, temp bool ff3, temp 4-component vector of float ff4}) 0:40 Constant: 0:40 4 (const int) -0:? 's_ff1' ( in bool Face) +0:? 's_ff1' ( flat in bool Face) 0:40 move second child to first child ( temp bool) 0:40 ff2: direct index for structure ( temp bool) 0:? 's' ( temp structure{ temp 4-component vector of float a, temp bool b, temp 1-component vector of float c, temp 2-component vector of float d, temp bool ff1, temp bool ff2, temp bool ff3, temp 4-component vector of float ff4}) @@ -118,7 +118,7 @@ gl_FragCoord origin is upper left 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? 'input' (layout( location=0) in 4-component vector of float) 0:? 's' (layout( location=1) in structure{ smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, flat temp bool ff2, flat temp bool ff3, temp 4-component vector of float ff4}) -0:? 's_ff1' ( in bool Face) +0:? 's_ff1' ( flat in bool Face) Linked fragment stage: @@ -200,7 +200,7 @@ gl_FragCoord origin is upper left 0:? 's' ( temp structure{ temp 4-component vector of float a, temp bool b, temp 1-component vector of float c, temp 2-component vector of float d, temp bool ff1, temp bool ff2, temp bool ff3, temp 4-component vector of float ff4}) 0:40 Constant: 0:40 4 (const int) -0:? 's_ff1' ( in bool Face) +0:? 's_ff1' ( flat in bool Face) 0:40 move second child to first child ( temp bool) 0:40 ff2: direct index for structure ( temp bool) 0:? 's' ( temp structure{ temp 4-component vector of float a, temp bool b, temp 1-component vector of float c, temp 2-component vector of float d, temp bool ff1, temp bool ff2, temp bool ff3, temp 4-component vector of float ff4}) @@ -239,7 +239,7 @@ gl_FragCoord origin is upper left 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? 'input' (layout( location=0) in 4-component vector of float) 0:? 's' (layout( location=1) in structure{ smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, flat temp bool ff2, flat temp bool ff3, temp 4-component vector of float ff4}) -0:? 's_ff1' ( in bool Face) +0:? 's_ff1' ( flat in bool Face) // Module Version 10000 // Generated by (magic number): 80001 @@ -309,6 +309,7 @@ gl_FragCoord origin is upper left MemberDecorate 54(IN_S) 4 Flat MemberDecorate 54(IN_S) 5 Flat Decorate 56(s) Location 1 + Decorate 79(s_ff1) Flat Decorate 79(s_ff1) BuiltIn FrontFacing Decorate 94(@entryPointOutput) Location 0 MemberDecorate 101(myS) 0 Offset 0 diff --git a/Test/baseResults/hlsl.synthesizeInput.frag.out b/Test/baseResults/hlsl.synthesizeInput.frag.out new file mode 100755 index 00000000..aa77e25a --- /dev/null +++ b/Test/baseResults/hlsl.synthesizeInput.frag.out @@ -0,0 +1,151 @@ +hlsl.synthesizeInput.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:7 Function Definition: @main(struct-PSInput-f1-u11; ( temp 4-component vector of float) +0:7 Function Parameters: +0:7 'input' ( in structure{ temp float interp, temp uint no_interp}) +0:? Sequence +0:8 Branch: Return with expression +0:? Construct vec4 ( temp 4-component vector of float) +0:8 Convert uint to float ( temp float) +0:8 no_interp: direct index for structure ( temp uint) +0:8 'input' ( in structure{ temp float interp, temp uint no_interp}) +0:8 Constant: +0:8 1 (const int) +0:8 interp: direct index for structure ( temp float) +0:8 'input' ( in structure{ temp float interp, temp uint no_interp}) +0:8 Constant: +0:8 0 (const int) +0:8 Constant: +0:8 0.000000 +0:8 Constant: +0:8 1.000000 +0:7 Function Definition: main( ( temp void) +0:7 Function Parameters: +0:? Sequence +0:7 move second child to first child ( temp structure{ temp float interp, temp uint no_interp}) +0:? 'input' ( temp structure{ temp float interp, temp uint no_interp}) +0:? 'input' (layout( location=0) in structure{ temp float interp, flat temp uint no_interp}) +0:7 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:7 Function Call: @main(struct-PSInput-f1-u11; ( temp 4-component vector of float) +0:? 'input' ( temp structure{ temp float interp, temp uint no_interp}) +0:? Linker Objects +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:? 'input' (layout( location=0) in structure{ temp float interp, flat temp uint no_interp}) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:7 Function Definition: @main(struct-PSInput-f1-u11; ( temp 4-component vector of float) +0:7 Function Parameters: +0:7 'input' ( in structure{ temp float interp, temp uint no_interp}) +0:? Sequence +0:8 Branch: Return with expression +0:? Construct vec4 ( temp 4-component vector of float) +0:8 Convert uint to float ( temp float) +0:8 no_interp: direct index for structure ( temp uint) +0:8 'input' ( in structure{ temp float interp, temp uint no_interp}) +0:8 Constant: +0:8 1 (const int) +0:8 interp: direct index for structure ( temp float) +0:8 'input' ( in structure{ temp float interp, temp uint no_interp}) +0:8 Constant: +0:8 0 (const int) +0:8 Constant: +0:8 0.000000 +0:8 Constant: +0:8 1.000000 +0:7 Function Definition: main( ( temp void) +0:7 Function Parameters: +0:? Sequence +0:7 move second child to first child ( temp structure{ temp float interp, temp uint no_interp}) +0:? 'input' ( temp structure{ temp float interp, temp uint no_interp}) +0:? 'input' (layout( location=0) in structure{ temp float interp, flat temp uint no_interp}) +0:7 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:7 Function Call: @main(struct-PSInput-f1-u11; ( temp 4-component vector of float) +0:? 'input' ( temp structure{ temp float interp, temp uint no_interp}) +0:? Linker Objects +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:? 'input' (layout( location=0) in structure{ temp float interp, flat temp uint no_interp}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 44 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 33 40 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 8 "PSInput" + MemberName 8(PSInput) 0 "interp" + MemberName 8(PSInput) 1 "no_interp" + Name 13 "@main(struct-PSInput-f1-u11;" + Name 12 "input" + Name 30 "input" + Name 31 "PSInput" + MemberName 31(PSInput) 0 "interp" + MemberName 31(PSInput) 1 "no_interp" + Name 33 "input" + Name 40 "@entryPointOutput" + Name 41 "param" + MemberDecorate 31(PSInput) 1 Flat + Decorate 33(input) Location 0 + Decorate 40(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeInt 32 0 + 8(PSInput): TypeStruct 6(float) 7(int) + 9: TypePointer Function 8(PSInput) + 10: TypeVector 6(float) 4 + 11: TypeFunction 10(fvec4) 9(ptr) + 15: TypeInt 32 1 + 16: 15(int) Constant 1 + 17: TypePointer Function 7(int) + 21: 15(int) Constant 0 + 22: TypePointer Function 6(float) + 25: 6(float) Constant 0 + 26: 6(float) Constant 1065353216 + 31(PSInput): TypeStruct 6(float) 7(int) + 32: TypePointer Input 31(PSInput) + 33(input): 32(ptr) Variable Input + 39: TypePointer Output 10(fvec4) +40(@entryPointOutput): 39(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 30(input): 9(ptr) Variable Function + 41(param): 9(ptr) Variable Function + 34: 31(PSInput) Load 33(input) + 35: 6(float) CompositeExtract 34 0 + 36: 22(ptr) AccessChain 30(input) 21 + Store 36 35 + 37: 7(int) CompositeExtract 34 1 + 38: 17(ptr) AccessChain 30(input) 16 + Store 38 37 + 42: 8(PSInput) Load 30(input) + Store 41(param) 42 + 43: 10(fvec4) FunctionCall 13(@main(struct-PSInput-f1-u11;) 41(param) + Store 40(@entryPointOutput) 43 + Return + FunctionEnd +13(@main(struct-PSInput-f1-u11;): 10(fvec4) Function None 11 + 12(input): 9(ptr) FunctionParameter + 14: Label + 18: 17(ptr) AccessChain 12(input) 16 + 19: 7(int) Load 18 + 20: 6(float) ConvertUToF 19 + 23: 22(ptr) AccessChain 12(input) 21 + 24: 6(float) Load 23 + 27: 10(fvec4) CompositeConstruct 20 24 25 26 + ReturnValue 27 + FunctionEnd diff --git a/Test/hlsl.synthesizeInput.frag b/Test/hlsl.synthesizeInput.frag new file mode 100644 index 00000000..c4b2fa4c --- /dev/null +++ b/Test/hlsl.synthesizeInput.frag @@ -0,0 +1,9 @@ +struct PSInput { + float interp; + uint no_interp; +}; + +float4 main(PSInput input : INPUT) : SV_TARGET +{ + return float4(float(input.no_interp), input.interp, 0, 1); +} \ No newline at end of file diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index cdf5cea3..e2789aa1 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -275,6 +275,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.structin.vert", "main"}, {"hlsl.structIoFourWay.frag", "main"}, {"hlsl.structStructName.frag", "main"}, + {"hlsl.synthesizeInput.frag", "main"}, {"hlsl.texture.subvec4.frag", "main"}, {"hlsl.this.frag", "main"}, {"hlsl.intrinsics.vert", "VertexShaderFunction"}, diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index bc4cca8d..275cd981 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1527,8 +1527,6 @@ void HlslParseContext::fixBuiltInIoType(TType& type) // Variables that correspond to the user-interface in and out of a stage // (not the built-in interface) are // - assigned locations -// - corrected for interpolation -// * non-floating point values must be nointerpolation // - registered as a linkage node (part of the stage's external interface). // Assumes it is called in the order in which locations should be assigned. void HlslParseContext::assignToInterface(TVariable& variable) @@ -1554,21 +1552,6 @@ void HlslParseContext::assignToInterface(TVariable& variable) nextOutLocation += size; } } - if (qualifier.storage == EvqVaryingIn && language == EShLangFragment) { - // Going into the fragment stage, integer-based stuff must be flat/nointerpolation - const auto fixQualifier = [](TType& type) { - if (type.getQualifier().builtIn == EbvNone && - (type.isIntegerDomain() || type.getBasicType() == EbtBool)) { - type.getQualifier().clearInterpolation(); - type.getQualifier().flat = true; - } - }; - if (type.isStruct()) - for (auto mem = (*type.getStruct()).begin(); mem != (*type.getStruct()).end(); ++mem) - fixQualifier(*mem->type); - else - fixQualifier(type); - } trackLinkage(variable); } }; @@ -2134,12 +2117,63 @@ void HlslParseContext::handleFunctionBody(const TSourceLoc& loc, TFunction& func void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector& inputs, TVector& outputs) { + // We might have in input structure type with no decorations that caused it + // to look like an input type, yet it has (e.g.) interpolation types that + // must be modified that turn it into an input type. + // Hence, a missing ioTypeMap for 'input' might need to be synthesized. + const auto synthesizeEditedInput = [this](TType& type) { + // True if a type needs to be 'flat' + const auto needsFlat = [](const TType& type) { + return type.containsBasicType(EbtInt) || + type.containsBasicType(EbtUint) || + type.containsBasicType(EbtInt64) || + type.containsBasicType(EbtUint64) || + type.containsBasicType(EbtBool) || + type.containsBasicType(EbtDouble); + }; + + if (language == EShLangFragment && needsFlat(type)) { + if (type.isStruct()) { + TTypeList* finalList = nullptr; + auto it = ioTypeMap.find(type.getStruct()); + if (it == ioTypeMap.end() || it->second.input == nullptr) { + // Getting here means we have no input struct, but we need one. + auto list = new TTypeList; + for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { + TType* newType = new TType; + newType->shallowCopy(*member->type); + TTypeLoc typeLoc = { newType, member->loc }; + list->push_back(typeLoc); + } + // install the new input type + if (it == ioTypeMap.end()) { + tIoKinds newLists = { list, nullptr, nullptr }; + ioTypeMap[type.getStruct()] = newLists; + } else + it->second.input = list; + finalList = list; + } else + finalList = it->second.input; + // edit for 'flat' + for (auto member = finalList->begin(); member != finalList->end(); ++member) { + if (needsFlat(*member->type)) { + member->type->getQualifier().clearInterpolation(); + member->type->getQualifier().flat = true; + } + } + } else { + type.getQualifier().clearInterpolation(); + type.getQualifier().flat = true; + } + } + }; + // Do the actual work to make a type be a shader input or output variable, // and clear the original to be non-IO (for use as a normal function parameter/return). const auto makeIoVariable = [this](const char* name, TType& type, TStorageQualifier storage) -> TVariable* { TVariable* ioVariable = makeInternalVariable(name, type); clearUniformInputOutput(type.getQualifier()); - if (type.getStruct() != nullptr) { + if (type.isStruct()) { auto newLists = ioTypeMap.find(ioVariable->getType().getStruct()); if (newLists != ioTypeMap.end()) { if (storage == EvqVaryingIn && newLists->second.input) @@ -2192,6 +2226,7 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return for (int i = 0; i < function.getParamCount(); i++) { TType& paramType = *function[i].type; if (paramType.getQualifier().isParamInput()) { + synthesizeEditedInput(paramType); TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingIn); inputs.push_back(argAsGlobal);