<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/99154>99154</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Implement the `saturate` HLSL Function
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            metabug,
            backend:DirectX,
            HLSL,
            backend:SPIR-V,
            bot:HLSL
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          farzonl
      </td>
    </tr>
</table>

<pre>
    - [ ] Implement `saturate` clang builtin,
- [ ] Link `saturate` clang builtin with `hlsl_intrinsics.h`
- [ ] Add sema checks for `saturate` to `CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp`
- [ ] Add codegen for `saturate` to `EmitHLSLBuiltinExpr` in `CGBuiltin.cpp`
- [ ] Add codegen tests to `clang/test/CodeGenHLSL/builtins/saturate.hlsl`
- [ ] Add sema tests to `clang/test/SemaHLSL/BuiltIns/saturate-errors.hlsl`
- [ ] Create the `int_dx_saturate` intrinsic in `IntrinsicsDirectX.td`
- [ ] Create the `DXILOpMapping` of `int_dx_saturate` to  `7` in `DXIL.td`
- [ ] Create the `saturate.ll` and `saturate_errors.ll` tests in `llvm/test/CodeGen/DirectX/`
- [ ] Create the `int_spv_saturate` intrinsic in `IntrinsicsSPIRV.td`
- [ ] In SPIRVInstructionSelector.cpp create the `saturate` lowering and map  it to `int_spv_saturate` in `SPIRVInstructionSelector::selectIntrinsic`.
- [ ] Create SPIR-V backend test case in `llvm/test/CodeGen/SPIRV/hlsl-intrinsics/saturate.ll`

## DirectX

| DXIL Opcode | DXIL OpName | Shader Model | Shader Stages |
| ----------- | ----------- | ------------ | ------------- |
| 7 | Saturate | 6.0 | () |

## SPIR-V

# FClamp:

## Description:
**FClamp**  
 
Result is min(max(*x*, *minVal*), *maxVal*). Result is undefined if
*minVal* \> *maxVal*.The semantics used by min() and max() are those of
FMin and FMax.  
  
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.
Results are computed per component.

<table>
<colgroup>
<col style="width: 20%" />
<col style="width: 20%" />
<col style="width: 20%" />
<col style="width: 20%" />
<col style="width: 20%" />
</colgroup>
<thead>
<tr>
<th>Number</th>
<th>Operand 1</th>
<th>Operand 2</th>
<th>Operand 3</th>
<th>Operand 4</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p>43</p></td>
<td
class="tableblock halign-left valign-top"><p><em>&lt;id&gt;</em><br />
<em>x</em></p></td>
<td
class="tableblock halign-left valign-top"><p><em>&lt;id&gt;</em><br />
<em>minVal</em></p></td>
<td
class="tableblock halign-left valign-top"><p><em>&lt;id&gt;</em><br />
<em>maxVal</em></p></td>
<td></td>
</tr>
</tbody>
</table>



## Test Case(s)

 
 ### Example 1
```hlsl
//dxc saturate_test.hlsl -T lib_6_8 -enable-16bit-types -O0

export float4 fn(float4 p1) {
    return saturate(p1);
}
```
## HLSL:

Clamps the specified value within the range of 0 to 1.



| *ret* saturate(*x*) |
|---------------------|



 

## Parameters



| Item | Description |
|--------------------------------------------------------|----------------------------------------|
| <span id="x"></span><span id="X"></span>*x*<br/> | \[in\] The specified value.<br/> |



 

## Return Value

The *x* parameter, clamped within the range of 0 to 1.

## Type Description



| Name  | [**Template Type**](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/dx-graphics-hlsl-intrinsic-functions.md) | [**Component Type**](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/dx-graphics-hlsl-intrinsic-functions.md) | Size |
|-------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|--------------------------------|
| *x*   | [**scalar**](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/dx-graphics-hlsl-intrinsic-functions.md), **vector**, or **matrix** | [**float**](/windows/desktop/WinProg/windows-data-types) | any                            |
| *ret* | same as input *x* | [**float**](/windows/desktop/WinProg/windows-data-types) | same dimension(s) as input *x* |



 

## Minimum Shader Model

This function is supported in the following shader models.



| Shader Model | Supported |
|------------------------------------------------------------------------------------|-----------|
| [Shader Model 1 (DirectX HLSL)](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/dx-graphics-hlsl-sm1.md) and higher shader models | yes       |



 

## See also

<dl> <dt>

[**Intrinsic Functions (DirectX HLSL)**](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/dx-graphics-hlsl-intrinsic-functions.md)
</dt> </dl>
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUGF1z4yjy1-AXSi4ZxU784AdHjvdSNdmZmqTm5i2FBJa5QaAClDj7668asD7Gzsft3tXNqpRY0E1_N91ArRWV4nyF5tdovpnQ1u21We2o-UMrOSk0e1klGM2vMZpv8G3dSF5z5TBapJa61lDH0SLFpaSqwkUrpBMKkRyl637VJ6F-vLkAPwu3B4y9tPJRKGeEsqK00z1apCNSa8aw5TXF5Z6XPyzeafMzZadhJgf4Pz7df7oOLLatKp3QKqdSApZQgHXPa-oxhaqmZdOcY1dqxiuuXmd1Uws34HRzaEzPIf8tTr9H3nHrbKTojYPIFuYQ2eaa8d-4Ah6IbKPNLCLboyxTsNurpnqDMugfyXoxb0dkE26MNvYs9dxw6jh2ew5khXKP7PA4tE3nxWiI286rG2F46b5PHXub6Ob77afPzR1tGqEqIKl3r_ByGgPksjc7rH2XQWe-EBJUseHsY9Q-AIMRA3Epn-oT7yCyjYohsn3fWrZ5-qC57r_cfv12RpdbhT3oVllnWh_c91zy0mkDsYbLs7oCL6mfuRGq8hrXtMFYuBgf50XzqfIKL5StUba2ftQJjRbp9JwBgEjyDRe0_MEV80bFJbX8HcN63ohsIRCTfnsYZoCMEQovyRDJ8NEbYe4yxxAT-HMDCYcH499pHcb3e8q4wXeacTmcuHe04hZmIqGkf_A749OJZEDoMrCJOvjBYpr6X0SuEFkecTulggG7KbzNJa0b8MFIdW5LIxpwUwQReCOy_8YYpWv4-8ptKx0WFtewc1_V9OB5rw8eESRZ10J9o9KPl8cpeuimprgn0irGd0JxhsUuMO4WYzTPUXYzWj192HO_SyknSotbyxkuXqIoYIAQoofjyEBAa8uxBurbO6E8xvaOHqZBJfgHRHXDDVXM4rq1DlMpccExxbakkhqsDX7y4YufPblS141WUNjcS8OxsChd76SmTqgqabRQbkAekaPVHl4aDpqBDJBofrHeeXZjAYqQiRaCDbCmnemt1woEaB1nuOGml2Ya3ZrljhaSo-wmjEotK6PbZjiBrXsBlA0i5Fkwt0fZGpMUkTkiBMOm9HdGRmR7orTbc8r6kRkAUHbze1sX3ISlfmIA-xx8g2dvg8nb4Oxt8MUJGEZmNBprAN3WWX0Y9EvWBkP5UCikLn_gPZWiUonkO4efwrfTDSIElmY5mOoiStmEKWA64MhQuv7TpFGW8xp-yUI6lF0Lhsiigq_AKACzvDAjV_rpwxjl1xMwblu_upRhI_2olGdmT2NyFIUwMdh60nGheYACnlPLEbmyUBw8MJQWjwFINwcKxwY8A-giDa_vKYHOFpEtO5S4a7ug-vuWEycPWIricfF4hROuQIpktiiES2ADtTj5HAs-PzTaOOz36wu8g9IRv5tZKKLXfuvG2HDXGtXxQuTKY4CpoSJvhhL2WvoO-VhifQ21YTNveCl2gjPwbMv9KUYoDzJUVb4S-OZ0Nh3Zzpf3teEOSsdAlq7oLvseITn39F1BZ-9e2i_U0Jo7buzPTG8dr0Pn0_cH73D6wPMfLO07H5TltqEKCxYy5tBlBDR1DVVhMML5fg4nmgyyIyRH6J7mOZpfC-V_N_jh1FnTn5a8bs-vIWa-waoAAHKRMW6O1oa-qITY4OwDgRDTB9qFYbP2k8N8axoVug592wOvGwnNYmw94J1vELnaO9dYiFKfUZVw-7aYlhr66TtRGm31zm20b5qfhcoInCSlLiD7wizj9ofTTWJNGbPSN9AZ86kKSZpUhjZ7Udpk3Ignu3i4ttOaxejtJc671upXF_le_MFP8uEvZMafff4LLD9AYpCMMZZ_CrXQKv-iDovHEETWoY-PYpIcWvswqKkz4hCPOyPNfHUYKhYEZvp5ICQi238K9cXoqocmjDoays8xaKh6wW88IyvHLR9G_iBALRaqaV3ngf-ZlJ4dEzVXFvaZUK3P8n99I7wTStRtPTonHzdEYfHRQXAKtG0DJRlOgWEb3Gkp9bNQFbZhdQ2r7UldPD2Dd5T-cqH6eL4MnDa_Hok0g4N5vFkIfQFZ_r9yw9azuHnBaWMvqj03Y_N6C75wO47F89695xxTaXV34mTSl8YsZ65v_o6x2d304OPFqj1nmV907zh2tl4zHL9B3QlbZWyZLemEr2aXZDZbpFm6nOxXV1nKFwUpLssZnS_Ky0W2XPA5I1csvZrv0nIiViQlF-nlbEHSdJ4upzM2Z5fl5UW5pBfFstihi5TXVMiplE_1VJtqIqxt-Wq5nM0vJpIWXFp_CU9IzR0t2graHZIjQuJ1GcrW3Q1jhAQ7n6DFW6IOoB3K1kfc-WZiViBEUrSVRRepFNbZXiwnnOSr_qb_zAUikOocP2mNXL3h3Xip5zk2Rv-Llw6RrVce3Br0f1qRfwcAAP__w2MQ8Q">