|
@@ -2442,23 +2442,32 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
|
assert(hlsl::IsIntrinsicOp(callee) &&
|
|
assert(hlsl::IsIntrinsicOp(callee) &&
|
|
"doIntrinsicCallExpr was called for a non-intrinsic function.");
|
|
"doIntrinsicCallExpr was called for a non-intrinsic function.");
|
|
|
|
|
|
- const bool isFloatArg =
|
|
|
|
- isFloatOrVecMatOfFloatType(callExpr->getArg(0)->getType());
|
|
|
|
|
|
+ const bool isFloatType = isFloatOrVecMatOfFloatType(callExpr->getType());
|
|
|
|
+ const bool isSintType = isSintOrVecMatOfSintType(callExpr->getType());
|
|
GLSLstd450 glslOpcode = GLSLstd450Bad;
|
|
GLSLstd450 glslOpcode = GLSLstd450Bad;
|
|
- bool actOnEachVecInMat = false;
|
|
|
|
|
|
|
|
#define INTRINSIC_OP_CASE(intrinsicOp, glslOp, doEachVec) \
|
|
#define INTRINSIC_OP_CASE(intrinsicOp, glslOp, doEachVec) \
|
|
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
|
|
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
|
|
glslOpcode = GLSLstd450::GLSLstd450##glslOp; \
|
|
glslOpcode = GLSLstd450::GLSLstd450##glslOp; \
|
|
- actOnEachVecInMat = doEachVec; \
|
|
|
|
|
|
+ return processIntrinsicUsingGLSLInst(callExpr, glslOpcode, doEachVec); \
|
|
} break
|
|
} break
|
|
|
|
|
|
#define INTRINSIC_OP_CASE_INT_FLOAT(intrinsicOp, glslIntOp, glslFloatOp, \
|
|
#define INTRINSIC_OP_CASE_INT_FLOAT(intrinsicOp, glslIntOp, glslFloatOp, \
|
|
doEachVec) \
|
|
doEachVec) \
|
|
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
|
|
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
|
|
- glslOpcode = isFloatArg ? GLSLstd450::GLSLstd450##glslFloatOp \
|
|
|
|
- : GLSLstd450::GLSLstd450##glslIntOp; \
|
|
|
|
- actOnEachVecInMat = doEachVec; \
|
|
|
|
|
|
+ glslOpcode = isFloatType ? GLSLstd450::GLSLstd450##glslFloatOp \
|
|
|
|
+ : GLSLstd450::GLSLstd450##glslIntOp; \
|
|
|
|
+ return processIntrinsicUsingGLSLInst(callExpr, glslOpcode, doEachVec); \
|
|
|
|
+ } break
|
|
|
|
+
|
|
|
|
+#define INTRINSIC_OP_CASE_SINT_UINT_FLOAT(intrinsicOp, glslSintOp, glslUintOp, \
|
|
|
|
+ glslFloatOp, doEachVec) \
|
|
|
|
+ case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
|
|
|
|
+ glslOpcode = isFloatType \
|
|
|
|
+ ? GLSLstd450::GLSLstd450##glslFloatOp \
|
|
|
|
+ : isSintType ? GLSLstd450::GLSLstd450##glslSintOp \
|
|
|
|
+ : GLSLstd450::GLSLstd450##glslUintOp; \
|
|
|
|
+ return processIntrinsicUsingGLSLInst(callExpr, glslOpcode, doEachVec); \
|
|
} break
|
|
} break
|
|
|
|
|
|
// Figure out which intrinsic function to translate.
|
|
// Figure out which intrinsic function to translate.
|
|
@@ -2479,7 +2488,7 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
|
case hlsl::IntrinsicOp::IOP_asuint:
|
|
case hlsl::IntrinsicOp::IOP_asuint:
|
|
return processIntrinsicAsType(callExpr);
|
|
return processIntrinsicAsType(callExpr);
|
|
case hlsl::IntrinsicOp::IOP_sign: {
|
|
case hlsl::IntrinsicOp::IOP_sign: {
|
|
- if (isFloatArg)
|
|
|
|
|
|
+ if (isFloatOrVecMatOfFloatType(callExpr->getArg(0)->getType()))
|
|
return processIntrinsicFloatSign(callExpr);
|
|
return processIntrinsicFloatSign(callExpr);
|
|
else
|
|
else
|
|
return processIntrinsicUsingGLSLInst(callExpr,
|
|
return processIntrinsicUsingGLSLInst(callExpr,
|
|
@@ -2494,6 +2503,7 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
|
INTRINSIC_OP_CASE(ceil, Ceil, true);
|
|
INTRINSIC_OP_CASE(ceil, Ceil, true);
|
|
INTRINSIC_OP_CASE(cos, Cos, true);
|
|
INTRINSIC_OP_CASE(cos, Cos, true);
|
|
INTRINSIC_OP_CASE(cosh, Cosh, true);
|
|
INTRINSIC_OP_CASE(cosh, Cosh, true);
|
|
|
|
+ INTRINSIC_OP_CASE(cross, Cross, false);
|
|
INTRINSIC_OP_CASE(degrees, Degrees, true);
|
|
INTRINSIC_OP_CASE(degrees, Degrees, true);
|
|
INTRINSIC_OP_CASE(radians, Radians, true);
|
|
INTRINSIC_OP_CASE(radians, Radians, true);
|
|
INTRINSIC_OP_CASE(determinant, Determinant, false);
|
|
INTRINSIC_OP_CASE(determinant, Determinant, false);
|
|
@@ -2503,8 +2513,15 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
|
INTRINSIC_OP_CASE(length, Length, false);
|
|
INTRINSIC_OP_CASE(length, Length, false);
|
|
INTRINSIC_OP_CASE(log, Log, true);
|
|
INTRINSIC_OP_CASE(log, Log, true);
|
|
INTRINSIC_OP_CASE(log2, Log2, true);
|
|
INTRINSIC_OP_CASE(log2, Log2, true);
|
|
|
|
+ INTRINSIC_OP_CASE_SINT_UINT_FLOAT(max, SMax, UMax, FMax, true);
|
|
|
|
+ INTRINSIC_OP_CASE(umax, UMax, true);
|
|
|
|
+ INTRINSIC_OP_CASE_SINT_UINT_FLOAT(min, SMin, UMin, FMin, true);
|
|
|
|
+ INTRINSIC_OP_CASE(umin, UMin, true);
|
|
INTRINSIC_OP_CASE(normalize, Normalize, false);
|
|
INTRINSIC_OP_CASE(normalize, Normalize, false);
|
|
|
|
+ INTRINSIC_OP_CASE(pow, Pow, true);
|
|
|
|
+ INTRINSIC_OP_CASE(reflect, Reflect, false);
|
|
INTRINSIC_OP_CASE(rsqrt, InverseSqrt, true);
|
|
INTRINSIC_OP_CASE(rsqrt, InverseSqrt, true);
|
|
|
|
+ INTRINSIC_OP_CASE(step, Step, true);
|
|
INTRINSIC_OP_CASE(sin, Sin, true);
|
|
INTRINSIC_OP_CASE(sin, Sin, true);
|
|
INTRINSIC_OP_CASE(sinh, Sinh, true);
|
|
INTRINSIC_OP_CASE(sinh, Sinh, true);
|
|
INTRINSIC_OP_CASE(tan, Tan, true);
|
|
INTRINSIC_OP_CASE(tan, Tan, true);
|
|
@@ -2520,7 +2537,7 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
|
#undef INTRINSIC_OP_CASE
|
|
#undef INTRINSIC_OP_CASE
|
|
#undef INTRINSIC_OP_CASE_INT_FLOAT
|
|
#undef INTRINSIC_OP_CASE_INT_FLOAT
|
|
|
|
|
|
- return processIntrinsicUsingGLSLInst(callExpr, glslOpcode, actOnEachVecInMat);
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t SPIRVEmitter::processIntrinsicMul(const CallExpr *callExpr) {
|
|
uint32_t SPIRVEmitter::processIntrinsicMul(const CallExpr *callExpr) {
|
|
@@ -2860,10 +2877,8 @@ uint32_t SPIRVEmitter::processIntrinsicUsingGLSLInst(
|
|
const CallExpr *callExpr, GLSLstd450 opcode, bool actPerRowForMatrices) {
|
|
const CallExpr *callExpr, GLSLstd450 opcode, bool actPerRowForMatrices) {
|
|
// Import the GLSL.std.450 extended instruction set.
|
|
// Import the GLSL.std.450 extended instruction set.
|
|
const uint32_t glslInstSetId = theBuilder.getGLSLExtInstSet();
|
|
const uint32_t glslInstSetId = theBuilder.getGLSLExtInstSet();
|
|
-
|
|
|
|
|
|
+ const uint32_t returnType = typeTranslator.translateType(callExpr->getType());
|
|
if (callExpr->getNumArgs() == 1u) {
|
|
if (callExpr->getNumArgs() == 1u) {
|
|
- const uint32_t returnType =
|
|
|
|
- typeTranslator.translateType(callExpr->getType());
|
|
|
|
const Expr *arg = callExpr->getArg(0);
|
|
const Expr *arg = callExpr->getArg(0);
|
|
const uint32_t argId = doExpr(arg);
|
|
const uint32_t argId = doExpr(arg);
|
|
|
|
|
|
@@ -2878,8 +2893,27 @@ uint32_t SPIRVEmitter::processIntrinsicUsingGLSLInst(
|
|
};
|
|
};
|
|
return processEachVectorInMatrix(arg, argId, actOnEachVec);
|
|
return processEachVectorInMatrix(arg, argId, actOnEachVec);
|
|
}
|
|
}
|
|
-
|
|
|
|
return theBuilder.createExtInst(returnType, glslInstSetId, opcode, {argId});
|
|
return theBuilder.createExtInst(returnType, glslInstSetId, opcode, {argId});
|
|
|
|
+ } else if (callExpr->getNumArgs() == 2u) {
|
|
|
|
+ const Expr *arg0 = callExpr->getArg(0);
|
|
|
|
+ const Expr *arg1 = callExpr->getArg(1);
|
|
|
|
+ const uint32_t arg0Id = doExpr(arg0);
|
|
|
|
+ const uint32_t arg1Id = doExpr(arg1);
|
|
|
|
+ // If the instruction does not operate on matrices, we can perform the
|
|
|
|
+ // instruction on each vector of the matrix.
|
|
|
|
+ if (actPerRowForMatrices &&
|
|
|
|
+ TypeTranslator::isSpirvAcceptableMatrixType(arg0->getType())) {
|
|
|
|
+ const auto actOnEachVec = [this, glslInstSetId, opcode, arg1Id](
|
|
|
|
+ uint32_t index, uint32_t vecType, uint32_t arg0RowId) {
|
|
|
|
+ const uint32_t arg1RowId =
|
|
|
|
+ theBuilder.createCompositeExtract(vecType, arg1Id, {index});
|
|
|
|
+ return theBuilder.createExtInst(vecType, glslInstSetId, opcode,
|
|
|
|
+ {arg0RowId, arg1RowId});
|
|
|
|
+ };
|
|
|
|
+ return processEachVectorInMatrix(arg0, arg0Id, actOnEachVec);
|
|
|
|
+ }
|
|
|
|
+ return theBuilder.createExtInst(returnType, glslInstSetId, opcode,
|
|
|
|
+ {arg0Id, arg1Id});
|
|
}
|
|
}
|
|
|
|
|
|
emitError("Unsupported intrinsic function %0.")
|
|
emitError("Unsupported intrinsic function %0.")
|