summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-09-09 11:39:04 -0700
committerGitHub <noreply@github.com>2021-09-09 11:39:04 -0700
commit28adf8917e53953dbfebd746410a427a55eed814 (patch)
treeb575bcdcc7860d64065e538d3fbf1d0466803aa3
parentcc075b76ee25876135584d31ec650776fcb69166 (diff)
`reinterpret` and 16-bit value packing. (#1933)
* `reinterpret` and 16-bit value packing. * Update `half-texture` cross-compile test reference result. * Revert inadvertent reformatting of slang-ir-inst-defs.h Co-authored-by: Yong He <yhe@nvidia.com>
-rw-r--r--build/visual-studio/slang/slang.vcxproj2
-rw-r--r--build/visual-studio/slang/slang.vcxproj.filters6
-rw-r--r--source/slang/core.meta.slang6
-rw-r--r--source/slang/slang-diagnostic-defs.h3
-rw-r--r--source/slang/slang-emit-hlsl.cpp31
-rw-r--r--source/slang/slang-emit.cpp3
-rw-r--r--source/slang/slang-ir-any-value-marshalling.cpp241
-rw-r--r--source/slang/slang-ir-any-value-marshalling.h7
-rw-r--r--source/slang/slang-ir-inst-defs.h2
-rw-r--r--source/slang/slang-ir-insts.h1
-rw-r--r--source/slang/slang-ir-lower-reinterpret.cpp109
-rw-r--r--source/slang/slang-ir-lower-reinterpret.h16
-rw-r--r--source/slang/slang-ir.cpp12
-rw-r--r--tests/compute/half-texture.slang.1.expected14
-rw-r--r--tests/compute/pack-any-value-16bit.slang65
-rw-r--r--tests/compute/pack-any-value-16bit.slang.expected.txt4
16 files changed, 490 insertions, 32 deletions
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj
index 0ccd5ed70..a3c50525f 100644
--- a/build/visual-studio/slang/slang.vcxproj
+++ b/build/visual-studio/slang/slang.vcxproj
@@ -251,6 +251,7 @@
<ClInclude Include="..\..\..\source\slang\slang-ir-lower-generic-function.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-lower-generic-type.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-lower-generics.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-ir-lower-reinterpret.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-lower-tuple-types.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-missing-return.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-optix-entry-point-uniforms.h" />
@@ -380,6 +381,7 @@
<ClCompile Include="..\..\..\source\slang\slang-ir-lower-generic-function.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-lower-generic-type.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-lower-generics.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-ir-lower-reinterpret.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-lower-tuple-types.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-missing-return.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-optix-entry-point-uniforms.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters
index a7affb00a..c2acca94e 100644
--- a/build/visual-studio/slang/slang.vcxproj.filters
+++ b/build/visual-studio/slang/slang.vcxproj.filters
@@ -204,6 +204,9 @@
<ClInclude Include="..\..\..\source\slang\slang-ir-lower-generics.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-ir-lower-reinterpret.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-ir-lower-tuple-types.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -587,6 +590,9 @@
<ClCompile Include="..\..\..\source\slang\slang-ir-lower-generics.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-ir-lower-reinterpret.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ir-lower-tuple-types.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 28fd1a545..d2f574ef8 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1907,6 +1907,12 @@ __generic<T, U>
__intrinsic_op($(kIROp_CreateExistentialObject))
T createDynamicObject(uint typeId, U value);
+// Reinterpret
+__generic<T, U>
+[__unsafeForceInlineEarly]
+__intrinsic_op($(kIROp_Reinterpret))
+T reinterpret(U value);
+
// Specialized function
/// Given a string returns an integer hash of that string.
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index dcc62bdf7..b1f1bbaef 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -503,6 +503,9 @@ DIAGNOSTIC(41000, Warning, unreachableCode, "unreachable code detected")
DIAGNOSTIC(41010, Warning, missingReturn, "control flow may reach end of non-'void' function")
DIAGNOSTIC(41011, Error, typeDoesNotFitAnyValueSize, "type '$0' does not fit in the size required by its conforming interface.")
+
+DIAGNOSTIC(41012, Error, typeCannotBePackedIntoAnyValue, "type '$0' contains fields that cannot be packed into an AnyValue.")
+
//
// 5xxxx - Target code generation.
//
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 3921cbbac..2fda8ab99 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -479,7 +479,9 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
emitType(inst->getDataType());
m_writer->emit(")");
break;
-
+ case BaseType::Half:
+ m_writer->emit("f16tof32");
+ break;
case BaseType::Float:
// Note: at present HLSL only supports
// reinterpreting integer bits as a `float`.
@@ -511,11 +513,18 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
case BaseType::UInt:
case BaseType::Int:
break;
-
+ case BaseType::UInt16:
+ case BaseType::Int16:
+ break;
case BaseType::Float:
m_writer->emit("asuint(");
closeCount++;
break;
+
+ case BaseType::Half:
+ m_writer->emit("f32tof16(");
+ closeCount++;
+ break;
}
emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
@@ -750,20 +759,32 @@ void HLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
case kIROp_VoidType:
case kIROp_BoolType:
case kIROp_Int8Type:
- case kIROp_Int16Type:
case kIROp_IntType:
case kIROp_Int64Type:
case kIROp_UInt8Type:
- case kIROp_UInt16Type:
case kIROp_UIntType:
case kIROp_UInt64Type:
case kIROp_FloatType:
case kIROp_DoubleType:
- case kIROp_HalfType:
{
m_writer->emit(getDefaultBuiltinTypeName(type->getOp()));
return;
}
+ case kIROp_Int16Type:
+ {
+ m_writer->emit("min16int");
+ return;
+ }
+ case kIROp_UInt16Type:
+ {
+ m_writer->emit("min16uint");
+ return;
+ }
+ case kIROp_HalfType:
+ {
+ m_writer->emit("min16float");
+ return;
+ }
case kIROp_StructType:
m_writer->emit(getName(type));
return;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 3da19cef1..951e6fad5 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -21,6 +21,7 @@
#include "slang-ir-lower-generics.h"
#include "slang-ir-lower-tuple-types.h"
#include "slang-ir-lower-bit-cast.h"
+#include "slang-ir-lower-reinterpret.h"
#include "slang-ir-optix-entry-point-uniforms.h"
#include "slang-ir-restructure.h"
#include "slang-ir-restructure-scoping.h"
@@ -327,6 +328,8 @@ Result linkAndOptimizeIR(
eliminateDeadCode(irModule);
+ lowerReinterpret(targetRequest, irModule, sink);
+
// For targets that supports dynamic dispatch, we need to lower the
// generics / interface types to ordinary functions and types using
// function pointers.
diff --git a/source/slang/slang-ir-any-value-marshalling.cpp b/source/slang/slang-ir-any-value-marshalling.cpp
index cd76e4430..b88dd79d1 100644
--- a/source/slang/slang-ir-any-value-marshalling.cpp
+++ b/source/slang/slang-ir-any-value-marshalling.cpp
@@ -99,6 +99,33 @@ namespace Slang
sink->diagnose(concreteType->sourceLoc, Diagnostics::typeDoesNotFitAnyValueSize, concreteType);
}
}
+ void ensureOffsetAt4ByteBoundary()
+ {
+ if (intraFieldOffset)
+ {
+ fieldOffset++;
+ intraFieldOffset = 0;
+ }
+ }
+ void ensureOffsetAt2ByteBoundary()
+ {
+ if (intraFieldOffset == 0)
+ return;
+ if (intraFieldOffset <= 2)
+ {
+ intraFieldOffset = 2;
+ return;
+ }
+ fieldOffset++;
+ intraFieldOffset = 0;
+ return;
+ }
+ void advanceOffset(uint32_t bytes)
+ {
+ intraFieldOffset += bytes;
+ fieldOffset += intraFieldOffset / 4;
+ intraFieldOffset = intraFieldOffset % 4;
+ }
};
void emitMarshallingCode(
@@ -208,6 +235,7 @@ namespace Slang
case kIROp_IntType:
case kIROp_FloatType:
{
+ ensureOffsetAt4ByteBoundary();
if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
{
auto srcVal = builder->emitLoad(concreteVar);
@@ -218,11 +246,12 @@ namespace Slang
anyValInfo->fieldKeys[fieldOffset]);
builder->emitStore(dstAddr, dstVal);
}
- fieldOffset++;
+ advanceOffset(4);
break;
}
case kIROp_UIntType:
{
+ ensureOffsetAt4ByteBoundary();
if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
{
auto srcVal = builder->emitLoad(concreteVar);
@@ -232,17 +261,56 @@ namespace Slang
anyValInfo->fieldKeys[fieldOffset]);
builder->emitStore(dstAddr, srcVal);
}
- fieldOffset++;
+ advanceOffset(4);
+ break;
+ }
+ case kIROp_Int16Type:
+ case kIROp_UInt16Type:
+ case kIROp_HalfType:
+ {
+ ensureOffsetAt2ByteBoundary();
+ if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
+ {
+ auto srcVal = builder->emitLoad(concreteVar);
+ if (dataType->getOp() == kIROp_HalfType)
+ {
+ srcVal = builder->emitBitCast(builder->getType(kIROp_UInt16Type), srcVal);
+ }
+ srcVal = builder->emitConstructorInst(builder->getType(kIROp_UIntType), 1, &srcVal);
+ auto dstAddr = builder->emitFieldAddress(
+ uintPtrType,
+ anyValueVar,
+ anyValInfo->fieldKeys[fieldOffset]);
+ auto dstVal = builder->emitLoad(dstAddr);
+ if (intraFieldOffset == 0)
+ {
+ srcVal = builder->emitBitAnd(
+ srcVal->getFullType(), srcVal,
+ builder->getIntValue(builder->getUIntType(), 0xFFFF));
+ dstVal = builder->emitBitAnd(
+ dstVal->getFullType(), dstVal,
+ builder->getIntValue(builder->getUIntType(), 0xFFFF0000));
+ }
+ else
+ {
+ srcVal = builder->emitShl(
+ srcVal->getFullType(), srcVal,
+ builder->getIntValue(builder->getUIntType(), 16));
+ dstVal = builder->emitBitAnd(
+ dstVal->getFullType(), dstVal,
+ builder->getIntValue(builder->getUIntType(), 0xFFFF));
+ }
+ dstVal = builder->emitBitOr(dstVal->getFullType(), dstVal, srcVal);
+ builder->emitStore(dstAddr, dstVal);
+ }
+ advanceOffset(2);
break;
}
case kIROp_UInt64Type:
case kIROp_Int64Type:
case kIROp_DoubleType:
case kIROp_Int8Type:
- case kIROp_Int16Type:
case kIROp_UInt8Type:
- case kIROp_UInt16Type:
- case kIROp_HalfType:
SLANG_UNIMPLEMENTED_X("AnyValue type packing for non 32-bit elements");
break;
default:
@@ -253,6 +321,7 @@ namespace Slang
virtual void marshalResourceHandle(IRBuilder* builder, IRType* dataType, IRInst* concreteVar) override
{
SLANG_UNUSED(dataType);
+ ensureOffsetAt4ByteBoundary();
if (fieldOffset + 1 < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
{
auto srcVal = builder->emitLoad(concreteVar);
@@ -269,7 +338,7 @@ namespace Slang
auto dstAddr2 = builder->emitFieldAddress(
uintPtrType, anyValueVar, anyValInfo->fieldKeys[fieldOffset + 1]);
builder->emitStore(dstAddr2, highBits);
- fieldOffset += 2;
+ advanceOffset(8);
}
}
};
@@ -302,6 +371,13 @@ namespace Slang
builder.emitStore(concreteTypedVar, param);
auto resultVar = builder.emitVar(anyValInfo->type);
+ // Initialize fields to 0 to prevent downstream compiler error.
+ for (uint32_t offset = 0; offset < (uint32_t)anyValInfo->fieldKeys.getCount(); offset++)
+ {
+ auto fieldAddr = builder.emitFieldAddress(builder.getUIntType(), resultVar, anyValInfo->fieldKeys[offset]);
+ builder.emitStore(fieldAddr, builder.getIntValue(builder.getUIntType(), 0));
+ }
+
TypePackingContext context;
context.anyValInfo = anyValInfo;
context.fieldOffset = context.intraFieldOffset = 0;
@@ -311,13 +387,6 @@ namespace Slang
context.validateAnyTypeSize(sharedContext->sink, type);
- // Initialize the rest of unused fields to 0 to prevent downstream compiler error.
- for (uint32_t offset = context.fieldOffset; offset < (uint32_t)anyValInfo->fieldKeys.getCount(); offset++)
- {
- auto fieldAddr = builder.emitFieldAddress(builder.getUIntType(), resultVar, context.anyValInfo->fieldKeys[offset]);
- builder.emitStore(fieldAddr, builder.getIntValue(builder.getUIntType(), 0));
- }
-
auto load = builder.emitLoad(resultVar);
builder.emitReturn(load);
return func;
@@ -332,6 +401,7 @@ namespace Slang
case kIROp_IntType:
case kIROp_FloatType:
{
+ ensureOffsetAt4ByteBoundary();
if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
{
auto srcAddr = builder->emitFieldAddress(
@@ -342,11 +412,12 @@ namespace Slang
srcVal = builder->emitBitCast(dataType, srcVal);
builder->emitStore(concreteVar, srcVal);
}
- fieldOffset++;
+ advanceOffset(4);
break;
}
case kIROp_UIntType:
{
+ ensureOffsetAt4ByteBoundary();
if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
{
auto srcAddr = builder->emitFieldAddress(
@@ -356,17 +427,55 @@ namespace Slang
auto srcVal = builder->emitLoad(srcAddr);
builder->emitStore(concreteVar, srcVal);
}
- fieldOffset++;
+ advanceOffset(4);
+ break;
+ }
+ case kIROp_Int16Type:
+ case kIROp_UInt16Type:
+ case kIROp_HalfType:
+ {
+ ensureOffsetAt2ByteBoundary();
+ if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
+ {
+ auto srcAddr = builder->emitFieldAddress(
+ uintPtrType,
+ anyValueVar,
+ anyValInfo->fieldKeys[fieldOffset]);
+ auto srcVal = builder->emitLoad(srcAddr);
+ if (intraFieldOffset == 0)
+ {
+ srcVal = builder->emitBitAnd(
+ srcVal->getFullType(), srcVal,
+ builder->getIntValue(builder->getUIntType(), 0xFFFF));
+ }
+ else
+ {
+ srcVal = builder->emitShr(
+ srcVal->getFullType(), srcVal,
+ builder->getIntValue(builder->getUIntType(), 16));
+ }
+ if (dataType->getOp() == kIROp_Int16Type)
+ {
+ srcVal = builder->emitConstructorInst(builder->getType(kIROp_Int16Type), 1, &srcVal);
+ }
+ else
+ {
+ srcVal = builder->emitConstructorInst(builder->getType(kIROp_UInt16Type), 1, &srcVal);
+ }
+ if (dataType->getOp() == kIROp_HalfType)
+ {
+ srcVal = builder->emitBitCast(dataType, srcVal);
+ }
+ builder->emitStore(concreteVar, srcVal);
+ }
+ advanceOffset(2);
break;
}
case kIROp_UInt64Type:
case kIROp_Int64Type:
case kIROp_DoubleType:
case kIROp_Int8Type:
- case kIROp_Int16Type:
case kIROp_UInt8Type:
- case kIROp_UInt16Type:
- case kIROp_HalfType:
SLANG_UNIMPLEMENTED_X("AnyValue type packing for non 32-bit elements");
break;
default:
@@ -377,6 +486,7 @@ namespace Slang
virtual void marshalResourceHandle(
IRBuilder* builder, IRType* dataType, IRInst* concreteVar) override
{
+ ensureOffsetAt4ByteBoundary();
if (fieldOffset + 1 < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
{
auto srcAddr = builder->emitFieldAddress(
@@ -390,7 +500,7 @@ namespace Slang
auto combinedBits = builder->emitMakeUInt64(lowBits, highBits);
combinedBits = builder->emitBitCast(dataType, combinedBits);
builder->emitStore(concreteVar, combinedBits);
- fieldOffset += 2;
+ advanceOffset(8);
}
}
};
@@ -541,4 +651,97 @@ namespace Slang
context.sharedContext = sharedContext;
context.processModule();
}
+
+ SlangInt alignUp(SlangInt x, SlangInt alignment)
+ {
+ return (x + alignment - 1) / alignment * alignment;
+ }
+
+ SlangInt _getAnyValueSizeRaw(IRType* type, SlangInt offset)
+ {
+ switch (type->getOp())
+ {
+ case kIROp_IntType:
+ case kIROp_FloatType:
+ case kIROp_UIntType:
+ return alignUp(offset, 4) + 4;
+ case kIROp_UInt64Type:
+ case kIROp_Int64Type:
+ case kIROp_DoubleType:
+ return -1;
+ case kIROp_Int16Type:
+ case kIROp_UInt16Type:
+ case kIROp_HalfType:
+ return alignUp(offset, 2) + 2;
+ case kIROp_UInt8Type:
+ case kIROp_Int8Type:
+ return -1;
+ case kIROp_VectorType:
+ {
+ auto vectorType = static_cast<IRVectorType*>(type);
+ auto elementType = vectorType->getElementType();
+ auto elementCount = getIntVal(vectorType->getElementCount());
+ for (IRIntegerValue i = 0; i < elementCount; i++)
+ {
+ offset = _getAnyValueSizeRaw(elementType, offset);
+ if (offset < 0) return offset;
+ }
+ return offset;
+ }
+ case kIROp_MatrixType:
+ {
+ auto matrixType = static_cast<IRMatrixType*>(type);
+ auto elementType = matrixType->getElementType();
+ auto colCount = getIntVal(matrixType->getColumnCount());
+ auto rowCount = getIntVal(matrixType->getRowCount());
+ for (IRIntegerValue i = 0; i < colCount; i++)
+ {
+ for (IRIntegerValue j = 0; j < rowCount; j++)
+ {
+ offset = _getAnyValueSizeRaw(elementType, offset);
+ if (offset < 0) return offset;
+ }
+ }
+ return offset;
+ }
+ case kIROp_StructType:
+ {
+ auto structType = cast<IRStructType>(type);
+ for (auto field : structType->getFields())
+ {
+ offset = _getAnyValueSizeRaw(field->getFieldType(), offset);
+ if (offset < 0) return offset;
+ }
+ return offset;
+ }
+ case kIROp_ArrayType:
+ {
+ auto arrayType = cast<IRArrayType>(type);
+ for (IRIntegerValue i = 0; i < getIntVal(arrayType->getElementCount()); i++)
+ {
+ offset = _getAnyValueSizeRaw(arrayType->getElementType(), offset);
+ if (offset < 0) return offset;
+ }
+ return offset;
+ }
+ case kIROp_InterfaceType:
+ {
+ // TODO: implement anyValue packing for interface types.
+ return -1;
+ }
+ default:
+ if (as<IRTextureTypeBase>(type) || as<IRSamplerStateTypeBase>(type))
+ {
+ return alignUp(offset, 4) + 8;
+ }
+ return -1;
+ }
+ }
+
+ SlangInt getAnyValueSize(IRType* type)
+ {
+ auto rawSize = _getAnyValueSizeRaw(type, 0);
+ if (rawSize < 0) return rawSize;
+ return alignUp(rawSize, 4);
+ }
}
diff --git a/source/slang/slang-ir-any-value-marshalling.h b/source/slang/slang-ir-any-value-marshalling.h
index 943b61aa3..3279eeaac 100644
--- a/source/slang/slang-ir-any-value-marshalling.h
+++ b/source/slang/slang-ir-any-value-marshalling.h
@@ -1,8 +1,11 @@
// slang-ir-any-value-marshalling.h
#pragma once
+#include "../core/slang-common.h"
+
namespace Slang
{
+ struct IRType;
struct SharedGenericsLoweringContext;
/// Generates functions that pack and unpack `AnyValue`s, and replaces
@@ -11,4 +14,8 @@ namespace Slang
/// This is a sub-pass of lower-generics.
void generateAnyValueMarshallingFunctions(
SharedGenericsLoweringContext* sharedContext);
+
+
+ /// Get the AnyValue size required to hold a value of `type`.
+ SlangInt getAnyValueSize(IRType* type);
}
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 797d9f69c..8e8a243a0 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -668,6 +668,7 @@ INST(ExtractTaggedUnionTag, extractTaggedUnionTag, 1, 0)
INST(ExtractTaggedUnionPayload, extractTaggedUnionPayload, 1, 0)
INST(BitCast, bitCast, 1, 0)
+INST(Reinterpret, reinterpret, 1, 0)
// Converts other resources (such as ByteAddressBuffer) to the equivalent StructuredBuffer
INST(GetEquivalentStructuredBuffer, getEquivalentStructuredBuffer, 1, 0)
@@ -708,4 +709,3 @@ INST_RANGE(Attr, PendingLayoutAttr, VarOffsetAttr)
#undef USE_OTHER
#undef INST_RANGE
#undef INST
-
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 0a1f3be8d..049801db1 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -2446,6 +2446,7 @@ struct IRBuilder
IRInst* emitWaveMaskMatch(IRType* type, IRInst* mask, IRInst* value);
IRInst* emitBitAnd(IRType* type, IRInst* left, IRInst* right);
+ IRInst* emitBitOr(IRType* type, IRInst* left, IRInst* right);
IRInst* emitBitNot(IRType* type, IRInst* value);
IRInst* emitAdd(IRType* type, IRInst* left, IRInst* right);
diff --git a/source/slang/slang-ir-lower-reinterpret.cpp b/source/slang/slang-ir-lower-reinterpret.cpp
new file mode 100644
index 000000000..a140bacad
--- /dev/null
+++ b/source/slang/slang-ir-lower-reinterpret.cpp
@@ -0,0 +1,109 @@
+#include "slang-ir-lower-reinterpret.h"
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+#include "slang-ir-layout.h"
+#include "slang-ir-any-value-marshalling.h"
+
+namespace Slang
+{
+
+struct ReinterpretLoweringContext
+{
+ TargetRequest* targetReq;
+ DiagnosticSink* sink;
+ IRModule* module;
+ SharedIRBuilder sharedBuilderStorage;
+ OrderedHashSet<IRInst*> workList;
+
+ void addToWorkList(IRInst* inst)
+ {
+ for (auto ii = inst->getParent(); ii; ii = ii->getParent())
+ {
+ if (as<IRGeneric>(ii))
+ return;
+ }
+
+ if (workList.Contains(inst))
+ return;
+
+ workList.Add(inst);
+ }
+
+ void processInst(IRInst* inst)
+ {
+ switch (inst->getOp())
+ {
+ case kIROp_Reinterpret:
+ processReinterpret(inst);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void processModule()
+ {
+ SharedIRBuilder* sharedBuilder = &sharedBuilderStorage;
+ sharedBuilder->module = module;
+ sharedBuilder->session = module->session;
+
+ // Deduplicate equivalent types.
+ sharedBuilder->deduplicateAndRebuildGlobalNumberingMap();
+
+ addToWorkList(module->getModuleInst());
+
+ while (workList.Count() != 0)
+ {
+ IRInst* inst = workList.getLast();
+
+ workList.removeLast();
+
+ processInst(inst);
+
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ addToWorkList(child);
+ }
+ }
+ }
+
+ void processReinterpret(IRInst* inst)
+ {
+ auto operand = inst->getOperand(0);
+ auto fromType = operand->getDataType();
+ auto toType = inst->getDataType();
+ SlangInt fromTypeSize = getAnyValueSize(fromType);
+ if (fromTypeSize < 0)
+ {
+ sink->diagnose(inst->sourceLoc, Slang::Diagnostics::typeCannotBePackedIntoAnyValue, fromType);
+ }
+ SlangInt toTypeSize = getAnyValueSize(toType);
+ if (toTypeSize < 0)
+ {
+ sink->diagnose(inst->sourceLoc, Slang::Diagnostics::typeCannotBePackedIntoAnyValue, toType);
+ }
+ SlangInt anyValueSize = Math::Max(fromTypeSize, toTypeSize);
+
+ IRBuilder builder;
+ builder.sharedBuilder = &sharedBuilderStorage;
+ builder.setInsertBefore(inst);
+ auto anyValueType = builder.getAnyValueType(builder.getIntValue(builder.getUIntType(), anyValueSize));
+ auto packInst = builder.emitPackAnyValue(
+ anyValueType,
+ operand);
+ auto unpackInst = builder.emitUnpackAnyValue(toType, packInst);
+ inst->replaceUsesWith(unpackInst);
+ inst->removeAndDeallocate();
+ }
+};
+
+void lowerReinterpret(TargetRequest* targetReq, IRModule* module, DiagnosticSink* sink)
+{
+ ReinterpretLoweringContext context;
+ context.module = module;
+ context.targetReq = targetReq;
+ context.sink = sink;
+ context.processModule();
+}
+
+}
diff --git a/source/slang/slang-ir-lower-reinterpret.h b/source/slang/slang-ir-lower-reinterpret.h
new file mode 100644
index 000000000..623ccb32e
--- /dev/null
+++ b/source/slang/slang-ir-lower-reinterpret.h
@@ -0,0 +1,16 @@
+// slang-ir-lower-reinterpret.h
+#pragma once
+
+// This file defines an IR pass that lowers a reinterept<T>(U) operation, where T and U are any ordinary data types,
+// into a packAnyValue<T> followed by a unpackAnyValue<U> operation.
+
+namespace Slang
+{
+
+struct IRModule;
+class TargetRequest;
+class DiagnosticSink;
+
+void lowerReinterpret(TargetRequest* targetReq, IRModule* module, DiagnosticSink* sink);
+
+}
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 60aaafa83..601ebca26 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -4100,6 +4100,18 @@ namespace Slang
return inst;
}
+ IRInst* IRBuilder::emitBitOr(IRType* type, IRInst* left, IRInst* right)
+ {
+ auto inst = createInst<IRInst>(
+ this,
+ kIROp_BitOr,
+ type,
+ left,
+ right);
+ addInst(inst);
+ return inst;
+ }
+
IRInst* IRBuilder::emitBitNot(IRType* type, IRInst* value)
{
auto inst = createInst<IRInst>(
diff --git a/tests/compute/half-texture.slang.1.expected b/tests/compute/half-texture.slang.1.expected
index 7dd96403f..cd1f1e4f7 100644
--- a/tests/compute/half-texture.slang.1.expected
+++ b/tests/compute/half-texture.slang.1.expected
@@ -5,11 +5,11 @@ standard output = {
#pragma pack_matrix(column_major)
#line 8 "tests/compute/half-texture.slang"
-RWTexture2D<half > halfTexture_0 : register(u1);
+RWTexture2D<min16float > halfTexture_0 : register(u1);
-RWTexture2D<vector<half,2> > halfTexture2_0 : register(u2);
+RWTexture2D<vector<min16float,2> > halfTexture2_0 : register(u2);
-RWTexture2D<vector<half,4> > halfTexture4_0 : register(u3);
+RWTexture2D<vector<min16float,4> > halfTexture4_0 : register(u3);
#line 5
@@ -27,15 +27,15 @@ void computeMain(vector<uint,3> dispatchThreadID_0 : SV_DISPATCHTHREADID)
vector<int,2> pos2_0 = vector<int,2>(int(3) - pos_0.y, int(3) - pos_0.x);
#line 29
- half h_0 = halfTexture_0[(vector<uint,2>) pos2_0];
- vector<half,2> h2_0 = halfTexture2_0[(vector<uint,2>) pos2_0];
- vector<half,4> h4_0 = halfTexture4_0[(vector<uint,2>) pos2_0];
+ min16float h_0 = halfTexture_0[(vector<uint,2>) pos2_0];
+ vector<min16float,2> h2_0 = halfTexture2_0[(vector<uint,2>) pos2_0];
+ vector<min16float,4> h4_0 = halfTexture4_0[(vector<uint,2>) pos2_0];
halfTexture_0[(vector<uint,2>) pos_0] = h2_0.x + h2_0.y;
halfTexture2_0[(vector<uint,2>) pos_0] = h4_0.xy;
- halfTexture4_0[(vector<uint,2>) pos_0] = vector<half,4>(h2_0, h_0, h_0);
+ halfTexture4_0[(vector<uint,2>) pos_0] = vector<min16float,4>(h2_0, h_0, h_0);
int index_0 = pos_0.x + pos_0.y * int(4);
outputBuffer_0[(uint) index_0] = index_0;
diff --git a/tests/compute/pack-any-value-16bit.slang b/tests/compute/pack-any-value-16bit.slang
new file mode 100644
index 000000000..b4f41bb94
--- /dev/null
+++ b/tests/compute/pack-any-value-16bit.slang
@@ -0,0 +1,65 @@
+// Test anyvalue packing of 16bit types.
+
+//TEST_DISABLED(compute):COMPARE_COMPUTE_EX:-slang -compute -vk -output-using-type
+//TEST_DISABLED(compute):COMPARE_COMPUTE_EX:-slang -compute -cuda -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -profile sm_6_0 -use-dxil -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx11 -profile sm_5_0 -output-using-type
+
+[anyValueSize(32)]
+interface IInterface
+{
+ float run();
+}
+
+struct Val : IInterface
+{
+ int16_t v0;
+ float f0;
+ uint16_t v1;
+ float16_t v2;
+ half v3;
+ uint16_t v4;
+ float run()
+ {
+ return v0 + f0 + v1 + v2 + v3 + v4;
+ }
+};
+
+struct UserDefinedPackedType
+{
+ uint4 values[2];
+};
+
+//TEST_INPUT:ubuffer(data=[0 0 0], stride=4):out,name=gOutputBuffer
+RWStructuredBuffer<float> gOutputBuffer;
+
+//TEST_INPUT: type_conformance Val:IInterface = 11
+
+[numthreads(1, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ uint half_4_0 = 0x4400; // 4.0f
+ uint half_5_0 = 0x4500; // 5.0f
+
+ UserDefinedPackedType objStorage;
+ objStorage.values[0] = uint4(1, asuint(2.0), (3U | (half_4_0<<16)), (half_5_0 | (6<<16)));
+ objStorage.values[1] = 0;
+
+ IInterface dynamicObj = createDynamicObject<IInterface, UserDefinedPackedType>(11, objStorage);
+ float result = dynamicObj.run();
+ gOutputBuffer[0] = result;
+
+ Val v;
+ v.v0 = 1;
+ v.f0 = 2;
+ v.v1 = 3;
+ v.v2 = 4;
+ v.v3 = 5;
+ v.v4 = 6;
+ IInterface dynamicObj1 = createDynamicObject<IInterface, Val>(11, v);;
+ gOutputBuffer[1] = dynamicObj1.run();
+
+ var packed = reinterpret<UserDefinedPackedType, Val>(v);
+ var unpacked = reinterpret<Val, UserDefinedPackedType>(packed);
+ gOutputBuffer[2] = unpacked.run();
+}
diff --git a/tests/compute/pack-any-value-16bit.slang.expected.txt b/tests/compute/pack-any-value-16bit.slang.expected.txt
new file mode 100644
index 000000000..a285fe901
--- /dev/null
+++ b/tests/compute/pack-any-value-16bit.slang.expected.txt
@@ -0,0 +1,4 @@
+type: float
+21.0
+21.0
+21.0 \ No newline at end of file