Skip to content

Implement the faceforward HLSL Function #99114

@farzonl

Description

@farzonl
  • implement faceforward in the hlsl_intrinsics.h
  • Implement faceforward spirv target builtin in clang/include/clang/Basic/BuiltinsSPIRV.td
  • Add a spirv fast path in hlsl_detail.h in the form
#if (__has_builtin(__builtin_spirv_faceforward))
  return __builtin_spirv_faceforward(...);
#else
  return ...; // regular behavior
#endif

An alternative to doing a built-in here would be to do pattern matching. Say we have code like this

faceforward(p1, p2, p3) ->
    dResult = dot(p2, p3)
    if(dResult < 0)
        return 0 - dResult;
   return dResult;

We would expect the code gen to look something like this

faceforward(p1, p2, p3) ->
  dResult       = dot(p2, p3)
  cmpResult  = fcmp dResult, 0.0
  subResult   = fsub -0.0 p1
  select(cmpResult, p1, subResult)

that means we could pattern match in SPIRVCombine.td and SPIRVPreLegalizerCombiner.cpp to

select(
    fcmp(
        dot(p2, p3), 
        0),
    p1,
    0 - p1) 
  • Add codegen for spirv faceforward builtin to EmitSPIRVBuiltinExpr in SPIR.cpp
  • Add HLSL codegen tests to clang/test/CodeGenHLSL/builtins/faceforward.hlsl
  • Add SPIRV builtin codegen tests to clang/test/CodeGenSPIRV/Builtins/faceforward.c
  • Add sema tests to clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl
  • Add spirv sema tests to clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c
  • Create the int_spv_faceforward intrinsic in IntrinsicsSPIRV.td
  • In SPIRVInstructionSelector.cpp create the faceforward lowering and map it to int_spv_faceforward in SPIRVInstructionSelector::selectIntrinsic.
  • Create SPIR-V backend test case in llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
  • Create SPIR-V backend test case in llvm/test/CodeGen/SPIRV/opencl/faceforward.ll

DirectX

No DXIL Opcodes were found.

SPIR-V

FaceForward:

Description:

FaceForward

If the dot product of Nref and I is negative, the result is N,
otherwise it is -N.

The operands must all be a scalar or vector whose component type is
floating-point.

Result Type and the type of all operands must be the same type.

Number Operand 1 Operand 2 Operand 3 Operand 4

70

<id>
N

<id>
I

<id>
Nref

Test Case(s)

Example 1

//dxc faceforward_test.hlsl -T lib_6_8 -enable-16bit-types -O0

export float4 fn(float4 p1, float4 p2, float4 p3) {
    return faceforward(p1, p2, p3);
}

HLSL:

Flips the surface-normal (if needed) to face in a direction opposite to i; returns the result in n.

ret faceforward(n, i, ng)

This function uses the following formula: -n sign(dot(i, ng)).

Parameters

Item Description
n
[in] The resulting floating-point surface-normal vector.
i
[in] A floating-point, incident vector that points from the view position to the shading position.
ng
[in] A floating-point surface-normal vector.

Return Value

A floating-point, surface normal vector that is facing the view direction.

Type Description

Name Template Type Component Type Size
n vector float any
i vector float same dimension(s) as input n
ng vector float same dimensions as input n
ret vector float same dimensions as input n

Minimum Shader Model

This function is supported in the following shader models.

Shader Model Supported
Shader Model 2 (DirectX HLSL) and higher shader models yes
Shader Model 1 (DirectX HLSL) vs_1_1 and ps_1_4

See also

Intrinsic Functions (DirectX HLSL)

Metadata

Metadata

Assignees

Labels

HLSLHLSL Language Supportbackend:SPIR-Vbot:HLSLmetabugIssue to collect references to a group of similar or related issues.

Type

No type

Projects

Status

Needs Review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions