[spirv] Support casting to bool/int/float (vector) values (#500)

* [spirv] Translate casting to bool (vector) values

* Supported converting scalar/vector sint/uint/float values into
  scalar/vector bool values.

* [spirv] Translate casting to int (vector) values

* Supported converting scalar/vector bool/float values into
  scalar/vector sint/uint values.

* [spirv] Translate casting to float (vector) values

* Supported implicit/explicit casting from scalar/vector
  bool/sint/uint into scalar/vector float values
This commit is contained in:
Lei Zhang 2017-08-01 19:31:25 -04:00 коммит произвёл David Peixotto
Родитель f38109c154
Коммит c760e02232
14 изменённых файлов: 977 добавлений и 52 удалений

Просмотреть файл

@ -346,6 +346,23 @@ FOr `unary operators <https://msdn.microsoft.com/en-us/library/windows/desktop/b
- ``+`` requires no additional SPIR-V instructions.
- ``-`` is translated into ``OpSNegate`` and ``OpFNegate`` for (vectors of) integers and floats, respectively.
Casts
+++++
Casting between (vectors) of scalar types is translated according to the following table:
+------------+-------------------+-------------------+-------------------+-------------------+
| From \\ To | Bool | SInt | UInt | Float |
+------------+-------------------+-------------------+-------------------+-------------------+
| Bool | no-op | select between one and zero |
+------------+-------------------+-------------------+-------------------+-------------------+
| SInt | | no-op | ``OpBitcast`` | ``OpConvertSToF`` |
+------------+ +-------------------+-------------------+-------------------+
| UInt | compare with zero | ``OpBitcast`` | no-op | ``OpConvertUToF`` |
+------------+ +-------------------+-------------------+-------------------+
| Float | | ``OpConvertFToS`` | ``OpConvertFToU`` | no-op |
+------------+-------------------+-------------------+-------------------+-------------------+
Control flows
-------------

Просмотреть файл

@ -5629,7 +5629,14 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
}
bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
const VectorType *VTy = E->getType()->castAs<VectorType>();
// HLSL Change Begins.
const VectorType *VTy;
if (Info.getLangOpts().HLSL && hlsl::IsHLSLVecType(E->getType())) {
VTy = hlsl::ConvertHLSLVecMatTypeToExtVectorType(getEvalInfo().Ctx, E->getType());
} else {
VTy = E->getType()->castAs<VectorType>();
}
// HLSL Change Ends.
unsigned NElts = VTy->getNumElements();
const Expr *SE = E->getSubExpr();
@ -5733,7 +5740,11 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
while (CountElts < NumElements) {
// Handle nested vector initialization.
if (CountInits < NumInits
&& E->getInit(CountInits)->getType()->isVectorType()) {
&& (E->getInit(CountInits)->getType()->isVectorType() ||
// HLSL Change Begins.
(Info.getLangOpts().HLSL &&
hlsl::IsHLSLVecType(E->getInit(CountInits)->getType())))) {
// HLSL Change Ends.
APValue v;
if (!EvaluateVector(E->getInit(CountInits), v, Info))
return Error(E);

Просмотреть файл

@ -26,6 +26,13 @@ namespace spirv {
namespace {
/// Returns true if the given type is a bool or vector of bool type.
bool isBoolOrVecOfBoolType(QualType type) {
return type->isBooleanType() ||
(hlsl::IsHLSLVecType(type) &&
hlsl::GetHLSLVecElementType(type)->isBooleanType());
}
/// Returns true if the given type is a signed integer or vector of signed
/// integer type.
bool isSintOrVecOfSintType(QualType type) {
@ -568,42 +575,12 @@ public:
}
}
if (const auto *castExpr = dyn_cast<ImplicitCastExpr>(expr)) {
return doImplicitCastExpr(castExpr);
}
if (const auto *cxxFunctionalCastExpr =
dyn_cast<CXXFunctionalCastExpr>(expr)) {
// Explicit cast is a NO-OP (e.g. vector<float, 4> -> float4)
if (cxxFunctionalCastExpr->getCastKind() == CK_NoOp) {
return doExpr(cxxFunctionalCastExpr->getSubExpr());
}
emitError("Found unhandled CXXFunctionalCastExpr cast type: %0")
<< cxxFunctionalCastExpr->getCastKindName();
return 0;
if (const auto *castExpr = dyn_cast<CastExpr>(expr)) {
return doCastExpr(castExpr);
}
if (const auto *initListExpr = dyn_cast<InitListExpr>(expr)) {
// First try to evaluate the expression as constant expression
Expr::EvalResult evalResult;
if (expr->EvaluateAsRValue(evalResult, astContext) &&
!evalResult.HasSideEffects) {
return translateAPValue(evalResult.Val, expr->getType());
}
const uint32_t resultType =
typeTranslator.translateType(initListExpr->getType());
// Special case for vectors of size 1.
if (initListExpr->getNumInits() == 1) {
return doExpr(initListExpr->getInit(0));
}
std::vector<uint32_t> constituents;
for (size_t i = 0; i < initListExpr->getNumInits(); ++i) {
constituents.push_back(doExpr(initListExpr->getInit(i)));
}
return theBuilder.createCompositeConstruct(resultType, constituents);
return doInitListExpr(initListExpr);
}
if (const auto *boolLiteral = dyn_cast<CXXBoolLiteralExpr>(expr)) {
@ -646,6 +623,77 @@ public:
return 0;
}
uint32_t doInitListExpr(const InitListExpr *expr) {
// First try to evaluate the expression as constant expression
Expr::EvalResult evalResult;
if (expr->EvaluateAsRValue(evalResult, astContext) &&
!evalResult.HasSideEffects) {
return translateAPValue(evalResult.Val, expr->getType());
}
const QualType type = expr->getType();
// InitListExpr is tricky to handle. It can have initializers of different
// types, and each initializer can itself be of a composite type.
// The front end parsing only gurantees the total number of elements in
// the initializers are the same as the one of the InitListExpr's type.
// For builtin types, we can assume the front end parsing has injected
// the necessary ImplicitCastExpr for type casting. So we just need to
// return the result of processing the only initializer.
if (type->isBuiltinType()) {
assert(expr->getNumInits() == 1);
return doExpr(expr->getInit(0));
}
// For composite types, we need to type cast the initializers if necessary.
const auto initCount = expr->getNumInits();
const uint32_t resultType = typeTranslator.translateType(type);
// For InitListExpr of vector type and having one initializer, we can avoid
// composite extraction and construction.
if (initCount == 1 && hlsl::IsHLSLVecType(type)) {
const Expr *init = expr->getInit(0);
// If the initializer already have the correct type, we don't need to
// type cast.
if (init->getType() == type) {
return doExpr(init);
}
// For the rest, we can do type cast as a whole.
const auto targetElemType = hlsl::GetHLSLVecElementType(type);
if (targetElemType->isBooleanType()) {
return castToBool(init, type);
} else if (targetElemType->isIntegerType()) {
return castToInt(init, type);
} else if (targetElemType->isFloatingType()) {
return castToFloat(init, type);
} else {
emitError("unimplemented vector InitList cases");
expr->dump();
return 0;
}
}
// Cases needing composite extraction and construction
std::vector<uint32_t> constituents;
for (size_t i = 0; i < initCount; ++i) {
const Expr *init = expr->getInit(i);
if (!init->getType()->isBuiltinType()) {
emitError("unimplemented InitList initializer type");
init->dump();
return 0;
}
constituents.push_back(doExpr(init));
}
return theBuilder.createCompositeConstruct(resultType, constituents);
}
uint32_t doBinaryOperator(const BinaryOperator *expr) {
const auto opcode = expr->getOpcode();
@ -804,12 +852,24 @@ public:
return 0;
}
uint32_t doImplicitCastExpr(const ImplicitCastExpr *expr) {
uint32_t doCastExpr(const CastExpr *expr) {
const Expr *subExpr = expr->getSubExpr();
const QualType toType = expr->getType();
switch (expr->getCastKind()) {
case CastKind::CK_IntegralCast: {
case CastKind::CK_LValueToRValue: {
const uint32_t fromValue = doExpr(subExpr);
// Using lvalue as rvalue means we need to OpLoad the contents from
// the parameter/variable first.
const uint32_t resultType = typeTranslator.translateType(toType);
return theBuilder.createLoad(resultType, fromValue);
}
case CastKind::CK_NoOp:
return doExpr(subExpr);
case CastKind::CK_IntegralCast:
case CastKind::CK_FloatingToIntegral:
case CastKind::CK_HLSLCC_IntegralCast:
case CastKind::CK_HLSLCC_FloatingToIntegral: {
// Integer literals in the AST are represented using 64bit APInt
// themselves and then implicitly casted into the expected bitwidth.
// We need special treatment of integer literals here because generating
@ -819,12 +879,14 @@ public:
llvm::APSInt intValue;
if (expr->EvaluateAsInt(intValue, astContext, Expr::SE_NoSideEffects)) {
return translateAPInt(intValue, toType);
} else {
emitError("Integral cast is not supported yet");
return 0;
}
return castToInt(subExpr, toType);
}
case CastKind::CK_FloatingCast: {
case CastKind::CK_FloatingCast:
case CastKind::CK_IntegralToFloating:
case CastKind::CK_HLSLCC_FloatingCast:
case CastKind::CK_HLSLCC_IntegralToFloating: {
// First try to see if we can do constant folding for floating point
// numbers like what we are doing for integers in the above.
Expr::EvalResult evalResult;
@ -832,17 +894,22 @@ public:
!evalResult.HasSideEffects) {
return translateAPFloat(evalResult.Val.getFloat(), toType);
}
emitError("floating cast unimplemented");
return 0;
}
case CastKind::CK_LValueToRValue: {
const uint32_t fromValue = doExpr(subExpr);
// Using lvalue as rvalue means we need to OpLoad the contents from
// the parameter/variable first.
const uint32_t resultType = typeTranslator.translateType(toType);
return theBuilder.createLoad(resultType, fromValue);
}
return castToFloat(subExpr, toType);
}
case CastKind::CK_IntegralToBoolean:
case CastKind::CK_FloatingToBoolean:
case CastKind::CK_HLSLCC_IntegralToBoolean:
case CastKind::CK_HLSLCC_FloatingToBoolean: {
// First try to see if we can do constant folding.
bool boolVal;
if (!expr->HasSideEffects(astContext) &&
expr->EvaluateAsBooleanCondition(boolVal, astContext)) {
return theBuilder.getConstantBool(boolVal);
}
return castToBool(subExpr, toType);
}
case CastKind::CK_HLSLVectorSplat: {
const size_t size = hlsl::GetHLSLVecSize(expr->getType());
const uint32_t scalarValue = doExpr(subExpr);
@ -950,6 +1017,58 @@ public:
}
}
/// Processes the given expr, casts the result into the given bool (vector)
/// type and returns the <result-id> of the casted value.
uint32_t castToBool(const Expr *expr, QualType toBoolType) {
// Converting to bool means comparing with value zero.
const uint32_t fromVal = doExpr(expr);
if (isBoolOrVecOfBoolType(expr->getType()))
return fromVal;
const spv::Op spvOp = translateOp(BO_NE, expr->getType());
const uint32_t boolType = typeTranslator.translateType(toBoolType);
const uint32_t zeroVal = getValueZero(expr->getType());
return theBuilder.createBinaryOp(spvOp, boolType, fromVal, zeroVal);
}
/// Processes the given expr, casts the result into the given integer (vector)
/// type and returns the <result-id> of the casted value.
uint32_t castToInt(const Expr *expr, QualType toIntType) {
const QualType fromType = expr->getType();
const uint32_t intType = typeTranslator.translateType(toIntType);
const uint32_t fromVal = doExpr(expr);
if (isBoolOrVecOfBoolType(fromType)) {
const uint32_t one = getValueOne(toIntType);
const uint32_t zero = getValueZero(toIntType);
return theBuilder.createSelect(intType, fromVal, one, zero);
} else if (isSintOrVecOfSintType(fromType) ||
isUintOrVecOfUintType(fromType)) {
if (fromType == toIntType)
return fromVal;
// TODO: handle different bitwidths
return theBuilder.createUnaryOp(spv::Op::OpBitcast, intType, fromVal);
} else if (isFloatOrVecOfFloatType(fromType)) {
if (isSintOrVecOfSintType(toIntType)) {
return theBuilder.createUnaryOp(spv::Op::OpConvertFToS, intType,
fromVal);
} else if (isUintOrVecOfUintType(toIntType)) {
return theBuilder.createUnaryOp(spv::Op::OpConvertFToU, intType,
fromVal);
} else {
emitError("unimplemented casting to integer from floating point");
}
} else {
emitError("unimplemented casting to integer");
}
expr->dump();
return 0;
}
uint32_t processIntrinsicCallExpr(const CallExpr *callExpr) {
const FunctionDecl *callee = callExpr->getDirectCallee();
assert(hlsl::IsIntrinsicOp(callee) &&
@ -974,6 +1093,36 @@ public:
return 0;
}
uint32_t castToFloat(const Expr *expr, QualType toFloatType) {
const QualType fromType = expr->getType();
const uint32_t floatType = typeTranslator.translateType(toFloatType);
const uint32_t fromVal = doExpr(expr);
if (isBoolOrVecOfBoolType(fromType)) {
const uint32_t one = getValueOne(toFloatType);
const uint32_t zero = getValueZero(toFloatType);
return theBuilder.createSelect(floatType, fromVal, one, zero);
}
if (isSintOrVecOfSintType(fromType)) {
return theBuilder.createUnaryOp(spv::Op::OpConvertSToF, floatType,
fromVal);
}
if (isUintOrVecOfUintType(fromType)) {
return theBuilder.createUnaryOp(spv::Op::OpConvertUToF, floatType,
fromVal);
}
if (isFloatOrVecOfFloatType(fromType)) {
return fromVal;
}
emitError("unimplemented casting to floating point");
expr->dump();
return 0;
}
uint32_t doCallExpr(const CallExpr *callExpr) {
const FunctionDecl *callee = callExpr->getDirectCallee();
@ -1230,6 +1379,39 @@ case BO_##kind : { \
return 0;
}
/// Returns the <result-id> for constant value 0 of the given type.
uint32_t getValueZero(QualType type) {
if (type->isSignedIntegerType()) {
return theBuilder.getConstantInt32(0);
}
if (type->isUnsignedIntegerType()) {
return theBuilder.getConstantUint32(0);
}
if (type->isFloatingType()) {
return theBuilder.getConstantFloat32(0.0);
}
if (hlsl::IsHLSLVecType(type)) {
const QualType elemType = hlsl::GetHLSLVecElementType(type);
const uint32_t elemZeroId = getValueZero(elemType);
const size_t size = hlsl::GetHLSLVecSize(type);
if (size == 1)
return elemZeroId;
llvm::SmallVector<uint32_t, 4> elements(size, elemZeroId);
const uint32_t vecTypeId = typeTranslator.translateType(type);
return theBuilder.getConstantComposite(vecTypeId, elements);
}
emitError("getting value 0 for type '%0' unimplemented")
<< type.getAsString();
return 0;
}
/// Translates the given frontend APValue into its SPIR-V equivalent for the
/// given targetType.
uint32_t translateAPValue(const APValue &value, const QualType targetType) {

Просмотреть файл

@ -0,0 +1,103 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2uint_0_0:%\d+]] = OpConstantComposite %v2uint %uint_0 %uint_0
// CHECK: [[v3float_0_0_0:%\d+]] = OpConstantComposite %v3float %float_0 %float_0 %float_0
// CHECK: [[v2bool_1_1:%\d+]] = OpConstantComposite %v2bool %true %true
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
bool b;
int from1;
uint from2;
float from3;
bool1 vb1;
bool2 vb2;
bool3 vb3;
int1 vfrom1;
uint2 vfrom2;
float3 vfrom3;
// C style cast
// From constant (explicit)
// CHECK: OpStore %b %true
b = (bool)35;
// CHECK-NEXT: OpStore %b %false
b = (bool)0.0;
// From constant expr
// CHECK-NEXT: OpStore %b %true
b = (bool)(3.5 - 3.4);
// From variable (explicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %int %from1
// CHECK-NEXT: [[c1:%\d+]] = OpINotEqual %bool [[from1]] %int_0
// CHECK-NEXT: OpStore %b [[c1]]
b = (bool)from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %uint %from2
// CHECK-NEXT: [[c2:%\d+]] = OpINotEqual %bool [[from2]] %uint_0
// CHECK-NEXT: OpStore %b [[c2]]
b = (bool)from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c3:%\d+]] = OpFOrdNotEqual %bool [[from3]] %float_0
// CHECK-NEXT: OpStore %b [[c3]]
b = (bool)from3;
// C++ function style cast
// CHECK-NEXT: OpStore %b %false
b = bool(0);
// CHECK-NEXT: OpStore %b %true
b = bool(3.5);
// CHECK-NEXT: OpStore %b %true
b = bool(42 + 1);
// CHECK-NEXT: [[from4:%\d+]] = OpLoad %int %from1
// CHECK-NEXT: [[c4:%\d+]] = OpINotEqual %bool [[from4]] %int_0
// CHECK-NEXT: OpStore %b [[c4]]
b = bool(from1);
// CHECK-NEXT: [[from5:%\d+]] = OpLoad %uint %from2
// CHECK-NEXT: [[c5:%\d+]] = OpINotEqual %bool [[from5]] %uint_0
// CHECK-NEXT: OpStore %b [[c5]]
b = bool(from2);
// CHECK-NEXT: [[from6:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c6:%\d+]] = OpFOrdNotEqual %bool [[from6]] %float_0
// CHECK-NEXT: OpStore %b [[c6]]
b = bool(from3);
// Vector cases
// CHECK-NEXT: OpStore %vb1 %true
vb1 = (bool1)42;
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %int %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpINotEqual %bool [[vfrom1]] %int_0
// CHECK-NEXT: OpStore %vb1 [[vc1]]
vb1 = (bool1)vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2uint %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpINotEqual %v2bool [[vfrom2]] [[v2uint_0_0]]
// CHECK-NEXT: OpStore %vb2 [[vc2]]
vb2 = (bool2)vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpFOrdNotEqual %v3bool [[vfrom3]] [[v3float_0_0_0]]
// CHECK-NEXT: OpStore %vb3 [[vc3]]
vb3 = (bool3)vfrom3;
// CHECK-NEXT: OpStore %vb1 %true
vb1 = bool1(3.5);
// CHECK-NEXT: OpStore %vb2 [[v2bool_1_1]]
vb2 = bool2(1.1 + 1.2, 3.0);
// CHECK-NEXT: [[vfrom4:%\d+]] = OpLoad %int %vfrom1
// CHECK-NEXT: [[vc4:%\d+]] = OpINotEqual %bool [[vfrom4]] %int_0
// CHECK-NEXT: OpStore %vb1 [[vc4]]
vb1 = bool1(vfrom1);
// CHECK-NEXT: [[vfrom5:%\d+]] = OpLoad %v2uint %vfrom2
// CHECK-NEXT: [[vc5:%\d+]] = OpINotEqual %v2bool [[vfrom5]] [[v2uint_0_0]]
// CHECK-NEXT: OpStore %vb2 [[vc5]]
vb2 = bool2(vfrom2);
// CHECK-NEXT: [[vfrom6:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc6:%\d+]] = OpFOrdNotEqual %v3bool [[vfrom6]] [[v3float_0_0_0]]
// CHECK-NEXT: OpStore %vb3 [[vc6]]
vb3 = bool3(vfrom3);
}

Просмотреть файл

@ -0,0 +1,66 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2bool_1_0:%\d+]] = OpConstantComposite %v2bool %true %false
// CHECK: [[v3bool_0_1_1:%\d+]] = OpConstantComposite %v3bool %false %true %true
// CHECK: [[v2uint_0_0:%\d+]] = OpConstantComposite %v2uint %uint_0 %uint_0
// CHECK: [[v3float_0_0_0:%\d+]] = OpConstantComposite %v3float %float_0 %float_0 %float_0
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
bool b;
int from1;
uint from2;
float from3;
bool1 vb1;
bool2 vb2;
bool3 vb3;
int1 vfrom1;
uint2 vfrom2;
float3 vfrom3;
// CHECK: %vbc2 = OpVariable %_ptr_Function_v2bool Function [[v2bool_1_0]]
// CHECK: %vbc3 = OpVariable %_ptr_Function_v3bool Function [[v3bool_0_1_1]]
// From constant (implicit)
// CHECK: OpStore %b %true
b = 42;
// CHECK-NEXT: OpStore %b %false
b = 0.0;
// From constant expr
// CHECK-NEXT: OpStore %b %false
b = 35 - 35;
// From variable (implicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %int %from1
// CHECK-NEXT: [[c1:%\d+]] = OpINotEqual %bool [[from1]] %int_0
// CHECK-NEXT: OpStore %b [[c1]]
b = from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %uint %from2
// CHECK-NEXT: [[c2:%\d+]] = OpINotEqual %bool [[from2]] %uint_0
// CHECK-NEXT: OpStore %b [[c2]]
b = from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c3:%\d+]] = OpFOrdNotEqual %bool [[from3]] %float_0
// CHECK-NEXT: OpStore %b [[c3]]
b = from3;
// Vector cases
// See the beginning for generated code
bool2 vbc2 = {1, 15 - 15};
bool3 vbc3 = {0.0, 1.2 + 1.1, 3}; // Mixed
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %int %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpINotEqual %bool [[vfrom1]] %int_0
// CHECK-NEXT: OpStore %vb1 [[vc1]]
vb1 = vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2uint %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpINotEqual %v2bool [[vfrom2]] [[v2uint_0_0]]
// CHECK-NEXT: OpStore %vb2 [[vc2]]
vb2 = vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpFOrdNotEqual %v3bool [[vfrom3]] [[v3float_0_0_0]]
// CHECK-NEXT: OpStore %vb3 [[vc3]]
vb3 = vfrom3;
}

Просмотреть файл

@ -0,0 +1,104 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2float_1_1:%\d+]] = OpConstantComposite %v2float %float_1 %float_1
// CHECK: [[v2float_0_0:%\d+]] = OpConstantComposite %v2float %float_0 %float_0
// CHECK: [[v3float_1_2_n3:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_n3
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
float f;
uint from1;
bool from2;
int from3;
float1 vf1;
float2 vf2;
float3 vf3;
uint1 vfrom1;
bool2 vfrom2;
int3 vfrom3;
// C style cast
// From constant (explicit)
// CHECK: OpStore %f %float_1
f = (float)true;
// CHECK-NEXT: OpStore %f %float_4
f = (float)4u;
// From constant expr
// CHECK-NEXT: OpStore %f %float_n2
f = (float)(3 - 5);
// From variable (explicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %uint %from1
// CHECK-NEXT: [[c1:%\d+]] = OpConvertUToF %float [[from1]]
// CHECK-NEXT: OpStore %f [[c1]]
f = (float)from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %bool %from2
// CHECK-NEXT: [[c2:%\d+]] = OpSelect %float [[from2]] %float_1 %float_0
// CHECK-NEXT: OpStore %f [[c2]]
f = (float)from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %int %from3
// CHECK-NEXT: [[c3:%\d+]] = OpConvertSToF %float [[from3]]
// CHECK-NEXT: OpStore %f [[c3]]
f = (float)from3;
// C++ function style cast
// CHECK-NEXT: OpStore %f %float_0
f = float(false);
// CHECK-NEXT: OpStore %f %float_2
f = float(2u);
// CHECK-NEXT: OpStore %f %float_3
f = float(-1 + 4);
// CHECK-NEXT: [[from4:%\d+]] = OpLoad %uint %from1
// CHECK-NEXT: [[c4:%\d+]] = OpConvertUToF %float [[from4]]
// CHECK-NEXT: OpStore %f [[c4]]
f = float(from1);
// CHECK-NEXT: [[from5:%\d+]] = OpLoad %bool %from2
// CHECK-NEXT: [[c5:%\d+]] = OpSelect %float [[from5]] %float_1 %float_0
// CHECK-NEXT: OpStore %f [[c5]]
f = float(from2);
// CHECK-NEXT: [[from6:%\d+]] = OpLoad %int %from3
// CHECK-NEXT: [[c6:%\d+]] = OpConvertSToF %float [[from6]]
// CHECK-NEXT: OpStore %f [[c6]]
f = float(from3);
// Vector cases
// CHECK-NEXT: OpStore %vf1 %float_7
vf1 = (float1)7;
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %uint %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpConvertUToF %float [[vfrom1]]
// CHECK-NEXT: OpStore %vf1 [[vc1]]
vf1 = (float1)vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2bool %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpSelect %v2float [[vfrom2]] [[v2float_1_1]] [[v2float_0_0]]
// CHECK-NEXT: OpStore %vf2 [[vc2]]
vf2 = (float2)vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3int %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpConvertSToF %v3float [[vfrom3]]
// CHECK-NEXT: OpStore %vf3 [[vc3]]
vf3 = (float3)vfrom3;
// CHECK-NEXT: OpStore %vf1 %float_3
vf1 = float1(3);
// CHECK-NEXT: OpStore %vf3 [[v3float_1_2_n3]]
vf3 = float3(true, 2u, -3);
// CHECK-NEXT: [[vfrom4:%\d+]] = OpLoad %uint %vfrom1
// CHECK-NEXT: [[vc4:%\d+]] = OpConvertUToF %float [[vfrom4]]
// CHECK-NEXT: OpStore %vf1 [[vc4]]
vf1 = float1(vfrom1);
// CHECK-NEXT: [[vfrom5:%\d+]] = OpLoad %v2bool %vfrom2
// CHECK-NEXT: [[vc5:%\d+]] = OpSelect %v2float [[vfrom5]] [[v2float_1_1]] [[v2float_0_0]]
// CHECK-NEXT: OpStore %vf2 [[vc5]]
vf2 = float2(vfrom2);
// CHECK-NEXT: [[vfrom6:%\d+]] = OpLoad %v3int %vfrom3
// CHECK-NEXT: [[vc6:%\d+]] = OpConvertSToF %v3float [[vfrom6]]
// CHECK-NEXT: OpStore %vf3 [[vc6]]
vf3 = float3(vfrom3);
}

Просмотреть файл

@ -0,0 +1,64 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2float_1_0:%\d+]] = OpConstantComposite %v2float %float_1 %float_0
// CHECK: [[v3float_0_4_n3:%\d+]] = OpConstantComposite %v3float %float_0 %float_4 %float_n3
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
float f;
bool from1;
uint from2;
int from3;
float1 vf1;
float2 vf2;
float3 vf3;
bool1 vfrom1;
uint2 vfrom2;
int3 vfrom3;
// CHECK: %vfc2 = OpVariable %_ptr_Function_v2float Function [[v2float_1_0]]
// CHECK: %vfc3 = OpVariable %_ptr_Function_v3float Function [[v3float_0_4_n3]]
// From constant (implicit)
// CHECK: OpStore %f %float_1
f = true;
// CHECK-NEXT: OpStore %f %float_3
f = 3u;
// From constant expr
// CHECK-NEXT: OpStore %f %float_n1
f = 5 - 6;
// From variable (implicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %bool %from1
// CHECK-NEXT: [[c1:%\d+]] = OpSelect %float [[from1]] %float_1 %float_0
// CHECK-NEXT: OpStore %f [[c1]]
f = from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %uint %from2
// CHECK-NEXT: [[c2:%\d+]] = OpConvertUToF %float [[from2]]
// CHECK-NEXT: OpStore %f [[c2]]
f = from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %int %from3
// CHECK-NEXT: [[c3:%\d+]] = OpConvertSToF %float [[from3]]
// CHECK-NEXT: OpStore %f [[c3]]
f = from3;
// Vector cases
// See the beginning for generated code
float2 vfc2 = {true, false};
float3 vfc3 = {false, 4u, -3}; // Mixed
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %bool %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpSelect %float [[vfrom1]] %float_1 %float_0
// CHECK-NEXT: OpStore %vf1 [[vc1]]
vf1 = vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2uint %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpConvertUToF %v2float [[vfrom2]]
// CHECK-NEXT: OpStore %vf2 [[vc2]]
vf2 = vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3int %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpConvertSToF %v3float [[vfrom3]]
// CHECK-NEXT: OpStore %vf3 [[vc3]]
vf3 = vfrom3;
}

Просмотреть файл

@ -0,0 +1,103 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2int_1_1:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
// CHECK: [[v2int_0_0:%\d+]] = OpConstantComposite %v2int %int_0 %int_0
// CHECK: [[v2int_2_n3:%\d+]] = OpConstantComposite %v2int %int_2 %int_n3
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
int i;
uint from1;
bool from2;
float from3;
int1 vi1;
int2 vi2;
int3 vi3;
uint1 vfrom1;
bool2 vfrom2;
float3 vfrom3;
// C style cast
// From constant (explicit)
// CHECK: OpStore %i %int_1
i = (int)true;
// CHECK-NEXT: OpStore %i %int_3
i = (int)3.0;
// From constant expr
// CHECK-NEXT: OpStore %i %int_n2
i = (int)(3.4 - 5.5);
// From variable (explicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %uint %from1
// CHECK-NEXT: [[c1:%\d+]] = OpBitcast %int [[from1]]
// CHECK-NEXT: OpStore %i [[c1]]
i = (int)from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %bool %from2
// CHECK-NEXT: [[c2:%\d+]] = OpSelect %int [[from2]] %int_1 %int_0
// CHECK-NEXT: OpStore %i [[c2]]
i = (int)from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c3:%\d+]] = OpConvertFToS %int [[from3]]
// CHECK-NEXT: OpStore %i [[c3]]
i = (int)from3;
// C++ function style cast
// CHECK-NEXT: OpStore %i %int_0
i = int(false);
// CHECK-NEXT: OpStore %i %int_3
i = int(3.5);
// CHECK-NEXT: OpStore %i %int_5
i = int(3.3 + 2.2);
// CHECK-NEXT: [[from4:%\d+]] = OpLoad %uint %from1
// CHECK-NEXT: [[c4:%\d+]] = OpBitcast %int [[from4]]
// CHECK-NEXT: OpStore %i [[c4]]
i = int(from1);
// CHECK-NEXT: [[from5:%\d+]] = OpLoad %bool %from2
// CHECK-NEXT: [[c5:%\d+]] = OpSelect %int [[from5]] %int_1 %int_0
// CHECK-NEXT: OpStore %i [[c5]]
i = int(from2);
// CHECK-NEXT: [[from6:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c6:%\d+]] = OpConvertFToS %int [[from6]]
// CHECK-NEXT: OpStore %i [[c6]]
i = int(from3);
// Vector cases
// CHECK-NEXT: OpStore %vi1 %int_3
vi1 = (int1)3.6;
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %uint %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpBitcast %int [[vfrom1]]
// CHECK-NEXT: OpStore %vi1 [[vc1]]
vi1 = (int1)vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2bool %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpSelect %v2int [[vfrom2]] [[v2int_1_1]] [[v2int_0_0]]
// CHECK-NEXT: OpStore %vi2 [[vc2]]
vi2 = (int2)vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpConvertFToS %v3int [[vfrom3]]
// CHECK-NEXT: OpStore %vi3 [[vc3]]
vi3 = (int3)vfrom3;
// CHECK-NEXT: OpStore %vi1 %int_3
vi1 = int1(3.5);
// CHECK-NEXT: OpStore %vi2 [[v2int_2_n3]]
vi2 = int2(1.1 + 1.2, -3);
// CHECK-NEXT: [[vfrom4:%\d+]] = OpLoad %uint %vfrom1
// CHECK-NEXT: [[vc4:%\d+]] = OpBitcast %int [[vfrom4]]
// CHECK-NEXT: OpStore %vi1 [[vc4]]
vi1 = int1(vfrom1);
// CHECK-NEXT: [[vfrom5:%\d+]] = OpLoad %v2bool %vfrom2
// CHECK-NEXT: [[vc5:%\d+]] = OpSelect %v2int [[vfrom5]] [[v2int_1_1]] [[v2int_0_0]]
// CHECK-NEXT: OpStore %vi2 [[vc5]]
vi2 = int2(vfrom2);
// CHECK-NEXT: [[vfrom6:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc6:%\d+]] = OpConvertFToS %v3int [[vfrom6]]
// CHECK-NEXT: OpStore %vi3 [[vc6]]
vi3 = int3(vfrom3);
}

Просмотреть файл

@ -0,0 +1,64 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2int_1_0:%\d+]] = OpConstantComposite %v2int %int_1 %int_0
// CHECK: [[v3int_0_2_n3:%\d+]] = OpConstantComposite %v3int %int_0 %int_2 %int_n3
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
int i;
bool from1;
uint from2;
float from3;
int1 vi1;
int2 vi2;
int3 vi3;
bool1 vfrom1;
uint2 vfrom2;
float3 vfrom3;
// CHECK: %vic2 = OpVariable %_ptr_Function_v2int Function [[v2int_1_0]]
// CHECK: %vic3 = OpVariable %_ptr_Function_v3int Function [[v3int_0_2_n3]]
// From constant (implicit)
// CHECK: OpStore %i %int_1
i = true;
// CHECK-NEXT: OpStore %i %int_0
i = 0.0;
// From constant expr
// CHECK-NEXT: OpStore %i %int_n3
i = 1.1 - 4.3;
// From variable (implicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %bool %from1
// CHECK-NEXT: [[c1:%\d+]] = OpSelect %int [[from1]] %int_1 %int_0
// CHECK-NEXT: OpStore %i [[c1]]
i = from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %uint %from2
// CHECK-NEXT: [[c2:%\d+]] = OpBitcast %int [[from2]]
// CHECK-NEXT: OpStore %i [[c2]]
i = from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c3:%\d+]] = OpConvertFToS %int [[from3]]
// CHECK-NEXT: OpStore %i [[c3]]
i = from3;
// Vector cases
// See the beginning for generated code
int2 vic2 = {true, false};
int3 vic3 = {false, 1.1 + 1.2, -3}; // Mixed
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %bool %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpSelect %int [[vfrom1]] %int_1 %int_0
// CHECK-NEXT: OpStore %vi1 [[vc1]]
vi1 = vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2uint %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpBitcast %v2int [[vfrom2]]
// CHECK-NEXT: OpStore %vi2 [[vc2]]
vi2 = vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpConvertFToS %v3int [[vfrom3]]
// CHECK-NEXT: OpStore %vi3 [[vc3]]
vi3 = vfrom3;
}

Просмотреть файл

@ -0,0 +1,104 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2uint_1_1:%\d+]] = OpConstantComposite %v2uint %uint_1 %uint_1
// CHECK: [[v2uint_0_0:%\d+]] = OpConstantComposite %v2uint %uint_0 %uint_0
// CHECK: [[v2uint_2_3:%\d+]] = OpConstantComposite %v2uint %uint_2 %uint_3
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
uint i;
int from1;
bool from2;
float from3;
uint1 vi1;
uint2 vi2;
uint3 vi3;
int1 vfrom1;
bool2 vfrom2;
float3 vfrom3;
// C style cast
// From constant (explicit)
// CHECK: OpStore %i %uint_1
i = (uint)true;
// CHECK-NEXT: OpStore %i %uint_3
i = (uint)3.0;
// From constant expr
// CHECK-NEXT: OpStore %i %uint_2
i = (uint)(5.5 - 3.4);
// From variable (explicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %int %from1
// CHECK-NEXT: [[c1:%\d+]] = OpBitcast %uint [[from1]]
// CHECK-NEXT: OpStore %i [[c1]]
i = (uint)from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %bool %from2
// CHECK-NEXT: [[c2:%\d+]] = OpSelect %uint [[from2]] %uint_1 %uint_0
// CHECK-NEXT: OpStore %i [[c2]]
i = (uint)from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c3:%\d+]] = OpConvertFToU %uint [[from3]]
// CHECK-NEXT: OpStore %i [[c3]]
i = (uint)from3;
// C++ function style cast
// CHECK-NEXT: OpStore %i %uint_0
i = uint(false);
// CHECK-NEXT: OpStore %i %uint_3
i = uint(3.5);
// CHECK-NEXT: OpStore %i %uint_5
i = uint(3.3 + 2.2);
// CHECK-NEXT: [[from4:%\d+]] = OpLoad %int %from1
// CHECK-NEXT: [[c4:%\d+]] = OpBitcast %uint [[from4]]
// CHECK-NEXT: OpStore %i [[c4]]
i = uint(from1);
// CHECK-NEXT: [[from5:%\d+]] = OpLoad %bool %from2
// CHECK-NEXT: [[c5:%\d+]] = OpSelect %uint [[from5]] %uint_1 %uint_0
// CHECK-NEXT: OpStore %i [[c5]]
i = uint(from2);
// CHECK-NEXT: [[from6:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c6:%\d+]] = OpConvertFToU %uint [[from6]]
// CHECK-NEXT: OpStore %i [[c6]]
i = uint(from3);
// Vector cases
// CHECK-NEXT: OpStore %vi1 %uint_3
vi1 = (uint1)3.6;
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %int %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpBitcast %uint [[vfrom1]]
// CHECK-NEXT: OpStore %vi1 [[vc1]]
vi1 = (uint1)vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2bool %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpSelect %v2uint [[vfrom2]] [[v2uint_1_1]] [[v2uint_0_0]]
// CHECK-NEXT: OpStore %vi2 [[vc2]]
vi2 = (uint2)vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpConvertFToU %v3uint [[vfrom3]]
// CHECK-NEXT: OpStore %vi3 [[vc3]]
vi3 = (uint3)vfrom3;
// CHECK-NEXT: OpStore %vi1 %uint_3
vi1 = uint1(3.5);
// CHECK-NEXT: OpStore %vi2 [[v2uint_2_3]]
vi2 = uint2(1.1 + 1.2, 3);
// CHECK-NEXT: [[vfrom4:%\d+]] = OpLoad %int %vfrom1
// CHECK-NEXT: [[vc4:%\d+]] = OpBitcast %uint [[vfrom4]]
// CHECK-NEXT: OpStore %vi1 [[vc4]]
vi1 = uint1(vfrom1);
// CHECK-NEXT: [[vfrom5:%\d+]] = OpLoad %v2bool %vfrom2
// CHECK-NEXT: [[vc5:%\d+]] = OpSelect %v2uint [[vfrom5]] [[v2uint_1_1]] [[v2uint_0_0]]
// CHECK-NEXT: OpStore %vi2 [[vc5]]
vi2 = uint2(vfrom2);
// CHECK-NEXT: [[vfrom6:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc6:%\d+]] = OpConvertFToU %v3uint [[vfrom6]]
// CHECK-NEXT: OpStore %vi3 [[vc6]]
vi3 = uint3(vfrom3);
}

Просмотреть файл

@ -0,0 +1,64 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: [[v2uint_1_0:%\d+]] = OpConstantComposite %v2uint %uint_1 %uint_0
// CHECK: [[v3uint_0_2_3:%\d+]] = OpConstantComposite %v3uint %uint_0 %uint_2 %uint_3
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
uint i;
bool from1;
int from2;
float from3;
uint1 vi1;
uint2 vi2;
uint3 vi3;
bool1 vfrom1;
int2 vfrom2;
float3 vfrom3;
// CHECK: %vic2 = OpVariable %_ptr_Function_v2uint Function [[v2uint_1_0]]
// CHECK: %vic3 = OpVariable %_ptr_Function_v3uint Function [[v3uint_0_2_3]]
// From constant (implicit)
// CHECK: OpStore %i %uint_1
i = true;
// CHECK-NEXT: OpStore %i %uint_0
i = 0.0;
// From constant expr
// CHECK-NEXT: OpStore %i %uint_3
i = 4.3 - 1.1;
// From variable (implicit)
// CHECK-NEXT: [[from1:%\d+]] = OpLoad %bool %from1
// CHECK-NEXT: [[c1:%\d+]] = OpSelect %uint [[from1]] %uint_1 %uint_0
// CHECK-NEXT: OpStore %i [[c1]]
i = from1;
// CHECK-NEXT: [[from2:%\d+]] = OpLoad %int %from2
// CHECK-NEXT: [[c2:%\d+]] = OpBitcast %uint [[from2]]
// CHECK-NEXT: OpStore %i [[c2]]
i = from2;
// CHECK-NEXT: [[from3:%\d+]] = OpLoad %float %from3
// CHECK-NEXT: [[c3:%\d+]] = OpConvertFToU %uint [[from3]]
// CHECK-NEXT: OpStore %i [[c3]]
i = from3;
// Vector cases
// See the beginning for generated code
uint2 vic2 = {true, false};
uint3 vic3 = {false, 1.1 + 1.2, 3}; // Mixed
// CHECK-NEXT: [[vfrom1:%\d+]] = OpLoad %bool %vfrom1
// CHECK-NEXT: [[vc1:%\d+]] = OpSelect %uint [[vfrom1]] %uint_1 %uint_0
// CHECK-NEXT: OpStore %vi1 [[vc1]]
vi1 = vfrom1;
// CHECK-NEXT: [[vfrom2:%\d+]] = OpLoad %v2int %vfrom2
// CHECK-NEXT: [[vc2:%\d+]] = OpBitcast %v2uint [[vfrom2]]
// CHECK-NEXT: OpStore %vi2 [[vc2]]
vi2 = vfrom2;
// CHECK-NEXT: [[vfrom3:%\d+]] = OpLoad %v3float %vfrom3
// CHECK-NEXT: [[vc3:%\d+]] = OpConvertFToU %v3uint [[vfrom3]]
// CHECK-NEXT: OpStore %vi3 [[vc3]]
vi3 = vfrom3;
}

Просмотреть файл

@ -0,0 +1,19 @@
// Run: %dxc -T ps_6_0 -E main
void main() {
// CHECK-LABEL: %bb_entry = OpLabel
int a, b;
// CHECK: [[a0:%\d+]] = OpLoad %int %a
// CHECK-NEXT: OpStore %b [[a0]]
b = int(a);
uint1 c, d;
// CHECK-NEXT: [[c0:%\d+]] = OpLoad %uint %c
// CHECK-NEXT: OpStore %d [[c0]]
d = uint1(c);
float2 e, f;
// CHECK-NEXT: [[e0:%\d+]] = OpLoad %v2float %e
// CHECK-NEXT: OpStore %f [[e0]]
f = float2(e);
}

Просмотреть файл

@ -5,7 +5,10 @@
// CHECK-DAG: %float_2 = OpConstant %float 2
// CHECK-DAG: %float_3 = OpConstant %float 3
// CHECK-DAG: %float_4 = OpConstant %float 4
// CHECK-DAG: %int_1 = OpConstant %int 1
// CHECK-DAG: %int_2 = OpConstant %int 2
// CHECK-DAG: [[float4constant:%\d+]] = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
// CHECK-DAG: [[int2constant:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
// Stage IO variables
// CHECK-DAG: [[component:%\d+]] = OpVariable %_ptr_Input_float Input
@ -23,6 +26,9 @@ float4 main(float component: COLOR) : SV_TARGET {
// CHECK-NEXT: %n = OpVariable %_ptr_Function_v4float Function
// CHECK-NEXT: %o = OpVariable %_ptr_Function_v4float Function
// CHECK-NEXT: %p = OpVariable %_ptr_Function_v2int Function [[int2constant]]
// CHECK-NEXT: %q = OpVariable %_ptr_Function_v3int Function
// CHECK-NEXT: %x = OpVariable %_ptr_Function_uint Function
// Initializer already attached to the var definition
@ -52,6 +58,13 @@ float4 main(float component: COLOR) : SV_TARGET {
// CHECK-NEXT: OpStore %o [[oinit]]
float4 o = float4(1.0, j, 3.0, j); // Mixed case
int2 p = {1, 2}; // All components are constants
// CHECK-NEXT: [[b1:%\d+]] = OpLoad %int %b
// CHECK-NEXT: [[a1:%\d+]] = OpLoad %int %a
// CHECK-NEXT: [[qinit:%\d+]] = OpCompositeConstruct %v3int %int_4 [[b1]] [[a1]]
// CHECK-NEXT: OpStore %q [[qinit]]
int3 q = {4, b, a}; // Mixed cases
// CHECK-NEXT: OpStore %x %uint_1
uint1 x = uint1(1); // Special case: vector of size 1

Просмотреть файл

@ -43,7 +43,7 @@ TEST_F(FileTest, ScalarConstants) { runFileTest("constant.scalar.hlsl"); }
TEST_F(FileTest, VectorConstants) { runFileTest("constant.vector.hlsl"); }
// For variables
TEST_F(FileTest, VariableInitialier) { runFileTest("var.init.hlsl"); }
TEST_F(FileTest, VariableInitializer) { runFileTest("var.init.hlsl"); }
// For prefix/postfix increment/decrement
TEST_F(FileTest, UnaryOpPrefixIncrement) {
@ -137,6 +137,17 @@ TEST_F(FileTest, TernaryOpConditionalOp) {
runFileTest("ternary-op.cond-op.hlsl");
}
// For casting
TEST_F(FileTest, CastNoOp) { runFileTest("cast.no-op.hlsl"); }
TEST_F(FileTest, CastImplicit2Bool) { runFileTest("cast.2bool.implicit.hlsl"); }
TEST_F(FileTest, CastExplicit2Bool) { runFileTest("cast.2bool.explicit.hlsl"); }
TEST_F(FileTest, CastImplicit2SInt) { runFileTest("cast.2sint.implicit.hlsl"); }
TEST_F(FileTest, CastExplicit2SInt) { runFileTest("cast.2sint.explicit.hlsl"); }
TEST_F(FileTest, CastImplicit2UInt) { runFileTest("cast.2uint.implicit.hlsl"); }
TEST_F(FileTest, CastExplicit2UInt) { runFileTest("cast.2uint.explicit.hlsl"); }
TEST_F(FileTest, CastImplicit2FP) { runFileTest("cast.2fp.implicit.hlsl"); }
TEST_F(FileTest, CastExplicit2FP) { runFileTest("cast.2fp.explicit.hlsl"); }
// For if statements
TEST_F(FileTest, IfStmtPlainAssign) { runFileTest("if-stmt.plain.hlsl"); }
TEST_F(FileTest, IfStmtNestedIfStmt) { runFileTest("if-stmt.nested.hlsl"); }