Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for HLSL 2021 intrinsic functions 'select', 'and', 'or' #260

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//// HLSL 2017 adds enum and enum class declarations.
//
//enum class MyEnum {
// FIRST,
// SECOND,
// THIRD,
// FOURTH,
//};
//
//enum class E : min16int {
// E1 = 3,
// E2
//};
//
//enum Vertex : int {
// FIRST = 10,
// SECOND = -2,
// THIRD = 48,
// FOURTH = -25,
//};
//
//enum Day {
// MONDAY,
// TUESDAY,
// WEDNESDAY
//};
//
//int f(MyEnum v) {
// switch (v) {
// case MyEnum::FIRST:
// return 1;
// case MyEnum::SECOND:
// return 2;
// default:
// return 0;
// }
//}
//
//int g(Vertex v) {
// return v + SECOND;
//}
//
//int4 main() : SV_Target {
// return int3(f(MyEnum::FIRST), g(FOURTH), E::E1);
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//============================================
//
// Logical Operator Short Circuiting
//
//============================================

[numthreads(1,1,1)]
void main_short_circuiting() {
int3 X = {1, 1, 1};
int3 Y = {0, 0, 0};

// Fails in HLSL 2021 (the operands must be scalars)
bool3 Cond = X && Y;
bool3 Cond2 = X || Y;
int3 Z = X ? 1 : 0;

// Replacement functions were added in HLSL 2021
bool3 Cond3 = and(X, Y);
bool3 Cond4 = or(X, Y);
int3 Z2 = select(X, 1, 0);
}


////============================================
////
//// Template Functions and Data Types
////
////============================================
//
//template<typename T>
//void increment(inout T X) {
// X += 1;
//}
//
//template<>
//void increment(inout float3 X) {
// X.x += 1.0;
//}
//
//[numthreads(1,1,1)]
//void main_inferred_template_functions() {
// int X = 0;
// int3 Y = {0,0,0};
// float3 Z = {0.0,0.0,0.0};
// increment(X);
// increment(Y);
// increment(Z);
//}
//
//template<typename V, typename T>
//V cast(T X) {
// return (V)X;
//}
//
//[numthreads(1,1,1)]
//void main_explicit_template_functions() {
// int X = 1;
// uint Y = cast<uint>(X);
//}
//
//
////============================================
////
//// Member Operator Overloading
////
////============================================
//
//struct Pupper {
// int Fur;
//
// Pupper operator +(int MoarFur) {
// Pupper Val = {Fur + MoarFur};
// return Val;
// }
//
// bool operator <=(int y){
// return Fur <= y;
// }
//
// operator bool() {
// return Fur > 50;
// }
//};
//
//[numthreads(1, 1, 1)]
//void main_operator_overloading(uint tidx : SV_DispatchThreadId) {
// Pupper y = {0};
// for (Pupper x = y; x <= 100; x = x + 1) {
// if ((bool)x)
// y = y + 1;
// }
//}
//
//
////============================================
////
//// Bitfield Members in Data Types
////
////============================================
//
//struct ColorRGBA {
// uint R : 8;
// uint G : 8;
// uint B : 8;
// uint A : 8;
//};
//
//
////============================================
////
//// Strict Casting of User-defined Data Types
////
////============================================
//
//struct LinearRGB {
// float3 RGB;
//};
//
//struct LinearYCoCg {
// float3 YCoCg;
//};
//
//void Modify(inout LinearRGB V) {
// V.RGB.x += 1;
//}
//
//[numthreads(64, 1, 1)]
//void main_strict_casting() {
// // Implicit cast to LinearRGB fails in HLSL 2021
// LinearYCoCg V = {{0.0, 0.0, 0.0}};
// Modify(V);
//
// // Explicit cast to LinearRGB succeeds (because it's member layout is the same as LinearYCoCg)
// LinearYCoCg V2 = {{0.0, 0.0, 0.0}};
// Modify((LinearRGB)V2);
//}
25 changes: 25 additions & 0 deletions src/ShaderTools.CodeAnalysis.Hlsl/Symbols/IntrinsicFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,31 @@ static IntrinsicFunctions()
new ParameterSymbol("outputDecl0", "A string defining which shader outputs in stream 0 are streamed out.", f, IntrinsicTypes.String)
}));

allFunctions.AddRange(Create2(
"and",
"Logically ANDs the two operands. Equivalent to the boolean AND operator (&&) except it doesn't short-circuit.",
IntrinsicTypes.AllNumericTypes,
"x", "The first operand.",
"y", "The second operand.",
IntrinsicTypes.AllNumericTypes.Select(nt => nt.GetNumericTypeWithScalarType(ScalarType.Bool)).ToArray()));

allFunctions.AddRange(Create2(
"or",
"Logically ORs the two operands. Equivalent to the boolean OR operator (||) except it doesn't short-circuit.",
IntrinsicTypes.AllNumericTypes,
"x", "The first operand.",
"y", "The second operand.",
IntrinsicTypes.AllNumericTypes.Select(nt => nt.GetNumericTypeWithScalarType(ScalarType.Bool)).ToArray()));

allFunctions.AddRange(Create3(
"select",
"Returns the second parameter if the condition is true, or the third parameter if the condition is false. Equivalent to the ternary operator (?:) except it doesn't short-circuit.",
IntrinsicTypes.AllNumericTypes,
"condition", "The condition that determines which value to return.",
"t", "The value to return if condition is true.",
"f", "The value to return if condition is false.",
overrideParameterTypes1: IntrinsicTypes.AllNumericTypes.Select(nt => nt.GetNumericTypeWithScalarType(ScalarType.Bool)).ToArray()));

AllFunctions = allFunctions;
}

Expand Down