summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-emit-spirv.cpp21
-rw-r--r--source/slang/slang-ir-util.cpp21
-rw-r--r--source/slang/slang-ir-util.h2
-rw-r--r--source/slang/slang-lower-to-ir.cpp8
-rw-r--r--tests/spirv/swizzle-signed-typecast.slang26
5 files changed, 57 insertions, 21 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index ec9857ecf..8e8e7327b 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -7763,27 +7763,6 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
List<IRInst*>::makeRepeated(scalar, Index(numElems)));
}
- bool isSignedType(IRType* type)
- {
- switch (type->getOp())
- {
- case kIROp_FloatType:
- case kIROp_DoubleType:
- return true;
- case kIROp_IntType:
- case kIROp_Int16Type:
- case kIROp_Int64Type:
- case kIROp_Int8Type:
- return true;
- case kIROp_VectorType:
- return isSignedType(as<IRVectorType>(type)->getElementType());
- case kIROp_MatrixType:
- return isSignedType(as<IRMatrixType>(type)->getElementType());
- default:
- return false;
- }
- }
-
bool isFloatType(IRInst* type)
{
switch (type->getOp())
diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp
index 13742711c..a2ec15661 100644
--- a/source/slang/slang-ir-util.cpp
+++ b/source/slang/slang-ir-util.cpp
@@ -2348,4 +2348,25 @@ bool isInstHoistable(IROp op, IRType* type, IRInst* const* fixedArgs)
isSpecConstOpHoistable(op, type, fixedArgs);
}
+bool isSignedType(IRType* type)
+{
+ switch (type->getOp())
+ {
+ case kIROp_FloatType:
+ case kIROp_DoubleType:
+ return true;
+ case kIROp_IntType:
+ case kIROp_Int16Type:
+ case kIROp_Int64Type:
+ case kIROp_Int8Type:
+ return true;
+ case kIROp_VectorType:
+ return isSignedType(as<IRVectorType>(type)->getElementType());
+ case kIROp_MatrixType:
+ return isSignedType(as<IRMatrixType>(type)->getElementType());
+ default:
+ return false;
+ }
+}
+
} // namespace Slang
diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h
index cccec7e05..dccdf5457 100644
--- a/source/slang/slang-ir-util.h
+++ b/source/slang/slang-ir-util.h
@@ -417,6 +417,8 @@ constexpr bool anyOf(Range&& range, Predicate&& pred)
}
return false;
}
+
+bool isSignedType(IRType* type);
} // namespace Slang
#endif
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index a03c75d7d..df3507670 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -7855,6 +7855,14 @@ top:
// we simply form a pointer to each of the vector
// elements and write to them individually.
IRInst* irRightVal = getSimpleVal(context, right);
+
+ // If there is a mismatch between the signedness of the left and rigth values
+ // then emit a cast
+ if (isSignedType(swizzleInfo->type) != isSignedType(irRightVal->getDataType()))
+ {
+ irRightVal = builder->emitCast(swizzleInfo->type, irRightVal);
+ }
+
swizzledStore(
loweredBase.val,
irRightVal,
diff --git a/tests/spirv/swizzle-signed-typecast.slang b/tests/spirv/swizzle-signed-typecast.slang
new file mode 100644
index 000000000..459dd3860
--- /dev/null
+++ b/tests/spirv/swizzle-signed-typecast.slang
@@ -0,0 +1,26 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv
+
+// CHECK: %{{.*}} = OpBitcast %v2uint %{{.*}}
+
+RWTexture2D<uint3> tex;
+void fn(inout int2 origPos, uint offset)
+{
+ origPos.x += offset;
+ origPos.y += offset;
+}
+
+uint3 id(float3 coord)
+{
+ return uint3(coord);
+}
+
+[shader("compute")]
+[numthreads(1,1,1)]
+void main(uint3 threadId : SV_DispatchThreadID)
+{
+ uint3 index = id(threadId);
+ // Passing a uint3 swizzle as a parameter to a function expecting a int2 should result
+ // in an explicit typecast from unsigned to signed
+ fn(index.xy, 1);
+ tex[threadId.xy] = index;
+} \ No newline at end of file