Decompose OpIsFinite to avoid capability restrictions
authorsteve-lunarg <steve_gh@khasekhemwy.net>
Tue, 4 Apr 2017 02:05:21 +0000 (20:05 -0600)
committersteve-lunarg <steve_gh@khasekhemwy.net>
Tue, 4 Apr 2017 02:05:21 +0000 (20:05 -0600)
OpIsFinite is not available everywhere: decompose isfinite
to !isinf && !isnan.

Test/baseResults/hlsl.isfinite.frag.out [new file with mode: 0644]
Test/hlsl.isfinite.frag [new file with mode: 0644]
gtests/Hlsl.FromFile.cpp
hlsl/hlslParseHelper.cpp

diff --git a/Test/baseResults/hlsl.isfinite.frag.out b/Test/baseResults/hlsl.isfinite.frag.out
new file mode 100644 (file)
index 0000000..652777a
--- /dev/null
@@ -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 (file)
index 0000000..a788bed
--- /dev/null
@@ -0,0 +1,9 @@
+
+uniform float f;
+
+float4 main() : SV_Target0
+{
+    isfinite(f);
+
+    return 0;
+}
index 2a211bc..ac62259 100644 (file)
@@ -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"},
index 27c09a2..c6248f6 100755 (executable)
@@ -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
     }