From 13975525d7748580f17623cd66f8e8e9841d0b04 Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Mon, 3 Apr 2017 20:05:21 -0600 Subject: [PATCH] Decompose OpIsFinite to avoid capability restrictions OpIsFinite is not available everywhere: decompose isfinite to !isinf && !isnan. --- Test/baseResults/hlsl.isfinite.frag.out | 140 ++++++++++++++++++++++++++++++++ Test/hlsl.isfinite.frag | 9 ++ gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslParseHelper.cpp | 42 ++++++++++ 4 files changed, 192 insertions(+) create mode 100644 Test/baseResults/hlsl.isfinite.frag.out create mode 100644 Test/hlsl.isfinite.frag diff --git a/Test/baseResults/hlsl.isfinite.frag.out b/Test/baseResults/hlsl.isfinite.frag.out new file mode 100644 index 0000000..652777a --- /dev/null +++ b/Test/baseResults/hlsl.isfinite.frag.out @@ -0,0 +1,140 @@ +hlsl.isfinite.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:5 Function Definition: @main( ( temp 4-component vector of float) +0:5 Function Parameters: +0:? Sequence +0:6 Sequence +0:6 move second child to first child ( temp float) +0:6 '@finitetmp' ( temp float) +0:6 f: direct index for structure ( uniform float) +0:6 'anon@0' (layout( row_major std140) uniform block{ uniform float f}) +0:6 Constant: +0:6 0 (const uint) +0:6 logical-and ( temp bool) +0:6 Negate conditional ( temp bool) +0:6 isnan ( temp bool) +0:6 '@finitetmp' ( temp float) +0:6 Negate conditional ( temp bool) +0:6 isinf ( temp bool) +0:6 '@finitetmp' ( temp float) +0:8 Branch: Return with expression +0:8 Constant: +0:8 0.000000 +0:8 0.000000 +0:8 0.000000 +0:8 0.000000 +0:5 Function Definition: main( ( temp void) +0:5 Function Parameters: +0:? Sequence +0:5 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:5 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform float f}) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:5 Function Definition: @main( ( temp 4-component vector of float) +0:5 Function Parameters: +0:? Sequence +0:6 Sequence +0:6 move second child to first child ( temp float) +0:6 '@finitetmp' ( temp float) +0:6 f: direct index for structure ( uniform float) +0:6 'anon@0' (layout( row_major std140) uniform block{ uniform float f}) +0:6 Constant: +0:6 0 (const uint) +0:6 logical-and ( temp bool) +0:6 Negate conditional ( temp bool) +0:6 isnan ( temp bool) +0:6 '@finitetmp' ( temp float) +0:6 Negate conditional ( temp bool) +0:6 isinf ( temp bool) +0:6 '@finitetmp' ( temp float) +0:8 Branch: Return with expression +0:8 Constant: +0:8 0.000000 +0:8 0.000000 +0:8 0.000000 +0:8 0.000000 +0:5 Function Definition: main( ( temp void) +0:5 Function Parameters: +0:? Sequence +0:5 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:5 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform float f}) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 38 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 36 + ExecutionMode 4 OriginUpperLeft + Name 4 "main" + Name 9 "@main(" + Name 12 "@finitetmp" + Name 13 "$Global" + MemberName 13($Global) 0 "f" + Name 15 "" + Name 36 "@entryPointOutput" + MemberDecorate 13($Global) 0 Offset 0 + Decorate 13($Global) Block + Decorate 15 DescriptorSet 0 + Decorate 36(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypePointer Function 6(float) + 13($Global): TypeStruct 6(float) + 14: TypePointer Uniform 13($Global) + 15: 14(ptr) Variable Uniform + 16: TypeInt 32 1 + 17: 16(int) Constant 0 + 18: TypePointer Uniform 6(float) + 21: TypeBool + 31: 6(float) Constant 0 + 32: 7(fvec4) ConstantComposite 31 31 31 31 + 35: TypePointer Output 7(fvec4) +36(@entryPointOutput): 35(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 37: 7(fvec4) FunctionCall 9(@main() + Store 36(@entryPointOutput) 37 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 12(@finitetmp): 11(ptr) Variable Function + 19: 18(ptr) AccessChain 15 17 + 20: 6(float) Load 19 + Store 12(@finitetmp) 20 + 22: 6(float) Load 12(@finitetmp) + 23: 21(bool) IsNan 22 + 24: 21(bool) LogicalNot 23 + SelectionMerge 26 None + BranchConditional 24 25 26 + 25: Label + 27: 6(float) Load 12(@finitetmp) + 28: 21(bool) IsInf 27 + 29: 21(bool) LogicalNot 28 + Branch 26 + 26: Label + 30: 21(bool) Phi 24 10 29 25 + ReturnValue 32 + FunctionEnd diff --git a/Test/hlsl.isfinite.frag b/Test/hlsl.isfinite.frag new file mode 100644 index 0000000..a788bed --- /dev/null +++ b/Test/hlsl.isfinite.frag @@ -0,0 +1,9 @@ + +uniform float f; + +float4 main() : SV_Target0 +{ + isfinite(f); + + return 0; +} diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 2a211bc..ac62259 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -135,6 +135,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.inoutquals.frag", "main"}, {"hlsl.init.frag", "ShaderFunction"}, {"hlsl.init2.frag", "main"}, + {"hlsl.isfinite.frag", "main"}, {"hlsl.intrinsics.barriers.comp", "ComputeShaderFunction"}, {"hlsl.intrinsics.comp", "ComputeShaderFunction"}, {"hlsl.intrinsics.evalfns.frag", "main"}, diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 27c09a2..c6248f6 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -3860,6 +3860,48 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& break; } + case EOpIsFinite: + { + // Since OPIsFinite in SPIR-V is only supported with the Kernel capability, we translate + // it to !isnan && !isinf + + TIntermTyped* arg0 = node->getAsUnaryNode()->getOperand(); + + // We'll make a temporary in case the RHS is cmoplex + TVariable* tempArg = makeInternalVariable("@finitetmp", arg0->getType()); + tempArg->getWritableType().getQualifier().makeTemporary(); + + TIntermTyped* tmpArgAssign = intermediate.addAssign(EOpAssign, + intermediate.addSymbol(*tempArg, loc), + arg0, loc); + + TIntermAggregate* compoundStatement = intermediate.makeAggregate(tmpArgAssign, loc); + + TIntermTyped* isnan = handleUnaryMath(loc, "isnan", EOpIsNan, intermediate.addSymbol(*tempArg, loc)); + isnan->setType(TType(EbtBool)); + + TIntermTyped* notnan = handleUnaryMath(loc, "!", EOpLogicalNot, isnan); + notnan->setType(TType(EbtBool)); + + TIntermTyped* isinf = handleUnaryMath(loc, "isinf", EOpIsInf, intermediate.addSymbol(*tempArg, loc)); + isinf->setType(TType(EbtBool)); + + TIntermTyped* notinf = handleUnaryMath(loc, "!", EOpLogicalNot, isinf); + notinf->setType(TType(EbtBool)); + + TIntermTyped* andNode = handleBinaryMath(loc, "and", EOpLogicalAnd, notnan, notinf); + andNode->setType(TType(EbtBool)); + + compoundStatement = intermediate.growAggregate(compoundStatement, andNode); + compoundStatement->setOperator(EOpSequence); + compoundStatement->setLoc(loc); + compoundStatement->setType(TType(EbtVoid)); + + node = compoundStatement; + + break; + } + default: break; // most pass through unchanged } -- 2.7.4