[clang] 06c6bae - [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (#122202)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 14 09:11:57 PST 2025


Author: Deric Cheung
Date: 2025-01-14T09:11:54-08:00
New Revision: 06c6baeb521e321ffcb60fc0a411451e987cd98b

URL: https://github.com/llvm/llvm-project/commit/06c6baeb521e321ffcb60fc0a411451e987cd98b
DIFF: https://github.com/llvm/llvm-project/commit/06c6baeb521e321ffcb60fc0a411451e987cd98b.diff

LOG: [HLSL] Implement D3DCOLORtoUBYTE4 intrinsic (#122202)

Fixes #99092.

1. Defines the function `D3DCOLORtoUBYTE4` in
`clang/lib/Headers/hlsl/hlsl_intrinsics.h`.
2. Implements the function `D3DCOLORtoUBYTE4` as `d3d_color_to_ubyte4`
in `clang/lib/Headers/hlsl/hlsl_detail.h`
3. Adds a HLSL codegen test to
`clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl`
4. Adds sema tests to
`clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl`

Added: 
    clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl
    clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl

Modified: 
    clang/lib/Headers/hlsl/hlsl_detail.h
    clang/lib/Headers/hlsl/hlsl_intrinsics.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h
index 19d83ea5471c7c..3eb4a3dc861e36 100644
--- a/clang/lib/Headers/hlsl/hlsl_detail.h
+++ b/clang/lib/Headers/hlsl/hlsl_detail.h
@@ -41,6 +41,17 @@ constexpr enable_if_t<sizeof(U) == sizeof(T), U> bit_cast(T F) {
   return __builtin_bit_cast(U, F);
 }
 
+constexpr vector<uint, 4> d3d_color_to_ubyte4_impl(vector<float, 4> V) {
+  // Use the same scaling factor used by FXC, and DXC for DXIL
+  // (i.e., 255.001953)
+  // https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/lib/HLSL/HLOperationLower.cpp#L666C1-L697C2
+  // The DXC implementation refers to a comment on the following stackoverflow
+  // discussion to justify the scaling factor: "Built-in rounding, necessary
+  // because of truncation. 0.001953 * 256 = 0.5"
+  // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f
+  return V.zyxw * 255.001953f;
+}
+
 template <typename T>
 constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
 length_impl(T X) {

diff  --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index d2d3abd92ea6a8..378b18e18b71b6 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1878,6 +1878,23 @@ half3 cross(half3, half3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross)
 float3 cross(float3, float3);
 
+//===----------------------------------------------------------------------===//
+// D3DCOLORtoUBYTE4 builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T D3DCOLORtoUBYTE4(T x)
+/// \brief Converts a floating-point, 4D vector set by a D3DCOLOR to a UBYTE4.
+/// \param x [in] The floating-point vector4 to convert.
+///
+/// The return value is the UBYTE4 representation of the \a x parameter.
+///
+/// This function swizzles and scales components of the \a x parameter. Use this
+/// function to compensate for the lack of UBYTE4 support in some hardware.
+
+constexpr vector<uint, 4> D3DCOLORtoUBYTE4(vector<float, 4> V) {
+  return __detail::d3d_color_to_ubyte4_impl(V);
+}
+
 //===----------------------------------------------------------------------===//
 // rcp builtins
 //===----------------------------------------------------------------------===//

diff  --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl
new file mode 100644
index 00000000000000..990f0aa910f300
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -finclude-default-header -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s \
+// RUN:   -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK
+
+// CHECK-LABEL: D3DCOLORtoUBYTE4
+int4 test_D3DCOLORtoUBYTE4(float4 p1) {
+  // CHECK: %[[SCALED:.*]] = fmul [[FMFLAGS:.*]][[FLOAT_TYPE:<4 x float>]] %{{.*}}, splat (float 0x406FE01000000000)
+  // CHECK: %[[CONVERTED:.*]] = fptoui [[FLOAT_TYPE]] %[[SCALED]] to [[INT_TYPE:<4 x i32>]]
+  // CHECK: %[[SHUFFLED:.*]] = shufflevector [[INT_TYPE]] %[[CONVERTED]], [[INT_TYPE]] poison, <4 x i32> <i32 2, i32 1, i32 0, i32 3>
+  // CHECK: ret [[INT_TYPE]] %[[SHUFFLED]]
+  return D3DCOLORtoUBYTE4(p1);
+}

diff  --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl
new file mode 100644
index 00000000000000..e9ba851007c941
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify
+
+int4 test_too_few_arg() {
+  return D3DCOLORtoUBYTE4();
+  // expected-error at -1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but no arguments were provided}}
+}
+
+int4 test_too_many_arg(float4 v) {
+  return D3DCOLORtoUBYTE4(v, v);
+  // expected-error at -1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'V', but 2 arguments were provided}}
+}
+
+int4 float2_arg(float2 v) {
+    return D3DCOLORtoUBYTE4(v);
+    // expected-error at -1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}}
+    // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'vector<[...], 2>' to 'vector<[...], 4>' for 1st argument}}
+}
+
+struct S {
+  float4 f;
+};
+
+int4 struct_arg(S v) {
+    return D3DCOLORtoUBYTE4(v);
+    // expected-error at -1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}}
+    // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'S' to 'vector<float, 4>' (vector of 4 'float' values) for 1st argument}}
+}


        


More information about the cfe-commits mailing list