[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:
Родитель
f38109c154
Коммит
c760e02232
|
@ -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"); }
|
||||
|
|
Загрузка…
Ссылка в новой задаче