summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaizhangNV <149626564+kaizhangNV@users.noreply.github.com>2024-12-17 19:06:30 -0600
committerGitHub <noreply@github.com>2024-12-17 17:06:30 -0800
commit6f57e47a9e1675b011f023277b47cfc768d30da8 (patch)
treeed9d531c1e1e4f55650314956c485d5107130a21
parent49e912a9d0d6ca5f762ec11cd8cb918f182eb76e (diff)
Implement bitcast for 64-bit date type (#5895)
Close #5470 * implement bitcast for 64-bit date type * Move 'ensurePrelude' to base class to remove duplication * Assert on 'double' type for Metal target, as Metal doesn't have 'double' support
-rw-r--r--source/slang/slang-emit-c-like.cpp11
-rw-r--r--source/slang/slang-emit-c-like.h5
-rw-r--r--source/slang/slang-emit-glsl.cpp26
-rw-r--r--source/slang/slang-emit-hlsl.cpp37
-rw-r--r--source/slang/slang-emit-metal.cpp16
-rw-r--r--source/slang/slang-emit-metal.h4
-rw-r--r--source/slang/slang-emit-wgsl.cpp12
-rw-r--r--source/slang/slang-emit-wgsl.h4
-rw-r--r--tests/compute/bitcast-64bit.slang43
-rw-r--r--tests/compute/bitcast-64bit.slang.expected.txt5
10 files changed, 121 insertions, 42 deletions
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index f38adc67e..b70069d42 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -5137,4 +5137,15 @@ void CLikeSourceEmitter::emitModuleImpl(IRModule* module, DiagnosticSink* sink)
executeEmitActions(actions);
}
+void CLikeSourceEmitter::ensurePrelude(const char* preludeText)
+{
+ IRStringLit* stringLit;
+ if (!m_builtinPreludes.tryGetValue(preludeText, stringLit))
+ {
+ IRBuilder builder(m_irModule);
+ stringLit = builder.getStringValue(UnownedStringSlice(preludeText));
+ m_builtinPreludes[preludeText] = stringLit;
+ }
+ m_requiredPreludes.add(stringLit);
+}
} // namespace Slang
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index 7f6f32923..dd8e27674 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -678,6 +678,9 @@ protected:
String _emitLiteralOneWithType(int bitWidth);
+
+ virtual void ensurePrelude(const char* preludeText);
+
CodeGenContext* m_codeGenContext = nullptr;
IRModule* m_irModule = nullptr;
@@ -723,6 +726,8 @@ protected:
{
String requireComputeDerivatives;
} m_requiredAfter;
+
+ Dictionary<const char*, IRStringLit*> m_builtinPreludes;
};
} // namespace Slang
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index 2c2447c53..d6f3795e3 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -2030,6 +2030,32 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
emitType(inst->getDataType());
}
break;
+ case BaseType::Int64:
+ if (fromType == BaseType::Double)
+ {
+ m_writer->emit("int64_t(doubleBitsToInt64(");
+ emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
+ m_writer->emit("))");
+ return true;
+ }
+ else
+ {
+ emitType(inst->getDataType());
+ }
+ break;
+ case BaseType::UInt64:
+ if (fromType == BaseType::Double)
+ {
+ m_writer->emit("uint64_t(doubleBitsToUint64(");
+ emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
+ m_writer->emit("))");
+ return true;
+ }
+ else
+ {
+ emitType(inst->getDataType());
+ }
+ break;
case BaseType::Half:
switch (fromType)
{
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 824680b72..c43f075b2 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -11,6 +11,23 @@
namespace Slang
{
+static const char* kHLSLBuiltInPrelude64BitCast = R"(
+uint64_t _slang_asuint64(double x)
+{
+ uint32_t low;
+ uint32_t high;
+ asuint(x, low, high);
+ return ((uint64_t)high << 32) | low;
+}
+
+double _slang_asdouble(uint64_t x)
+{
+ uint32_t low = x & 0xFFFFFFFF;
+ uint32_t high = x >> 32;
+ return asdouble(low, high);
+}
+)";
+
void HLSLSourceEmitter::_emitHLSLDecorationSingleString(
const char* name,
IRFunc* entryPoint,
@@ -822,17 +839,12 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
//
// There is no current function (it seems)
// for bit-casting an `int16_t` to a `half`.
- //
- // TODO: There is an `asdouble` function
- // for converting two 32-bit integer values into
- // one `double`. We could use that for
- // bit casts of 64-bit values with a bit of
- // extra work, but doing so might be best
- // handled in an IR pass that legalizes
- // bit-casts.
- //
m_writer->emit("asfloat");
break;
+ case BaseType::Double:
+ ensurePrelude(kHLSLBuiltInPrelude64BitCast);
+ m_writer->emit("_slang_asdouble");
+ break;
}
m_writer->emit("(");
int closeCount = 1;
@@ -844,6 +856,8 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
diagnoseUnhandledInst(inst);
break;
+ case BaseType::Int64:
+ case BaseType::UInt64:
case BaseType::UInt:
case BaseType::Int:
case BaseType::Bool:
@@ -860,6 +874,11 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
m_writer->emit("asuint16(");
closeCount++;
break;
+ case BaseType::Double:
+ ensurePrelude(kHLSLBuiltInPrelude64BitCast);
+ m_writer->emit("_slang_asuint64(");
+ closeCount++;
+ break;
}
emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
diff --git a/source/slang/slang-emit-metal.cpp b/source/slang/slang-emit-metal.cpp
index 45a9e60ad..282d8f95c 100644
--- a/source/slang/slang-emit-metal.cpp
+++ b/source/slang/slang-emit-metal.cpp
@@ -263,18 +263,6 @@ void MetalSourceEmitter::emitEntryPointAttributesImpl(
}
}
-void MetalSourceEmitter::ensurePrelude(const char* preludeText)
-{
- IRStringLit* stringLit;
- if (!m_builtinPreludes.tryGetValue(preludeText, stringLit))
- {
- IRBuilder builder(m_irModule);
- stringLit = builder.getStringValue(UnownedStringSlice(preludeText));
- m_builtinPreludes[preludeText] = stringLit;
- }
- m_requiredPreludes.add(stringLit);
-}
-
void MetalSourceEmitter::emitMemoryOrderOperand(IRInst* inst)
{
auto memoryOrder = (IRMemoryOrder)getIntVal(inst);
@@ -1065,7 +1053,6 @@ void MetalSourceEmitter::emitSimpleTypeImpl(IRType* type)
case kIROp_UInt8Type:
case kIROp_UIntType:
case kIROp_FloatType:
- case kIROp_DoubleType:
case kIROp_HalfType:
{
m_writer->emit(getDefaultBuiltinTypeName(type->getOp()));
@@ -1093,6 +1080,9 @@ void MetalSourceEmitter::emitSimpleTypeImpl(IRType* type)
m_writer->emit(getName(type));
return;
+ case kIROp_DoubleType:
+ SLANG_UNEXPECTED("'double' type emitted");
+ return;
case kIROp_VectorType:
{
auto vecType = (IRVectorType*)type;
diff --git a/source/slang/slang-emit-metal.h b/source/slang/slang-emit-metal.h
index 17562b1c4..b67a5b801 100644
--- a/source/slang/slang-emit-metal.h
+++ b/source/slang/slang-emit-metal.h
@@ -22,13 +22,9 @@ public:
virtual RefObject* getExtensionTracker() SLANG_OVERRIDE { return m_extensionTracker; }
- Dictionary<const char*, IRStringLit*> m_builtinPreludes;
-
protected:
RefPtr<MetalExtensionTracker> m_extensionTracker;
- void ensurePrelude(const char* preludeText);
-
void emitMemoryOrderOperand(IRInst* inst);
virtual void emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniformParameterGroupType* type)
SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit-wgsl.cpp b/source/slang/slang-emit-wgsl.cpp
index 0e45fd4cf..da5e38327 100644
--- a/source/slang/slang-emit-wgsl.cpp
+++ b/source/slang/slang-emit-wgsl.cpp
@@ -49,18 +49,6 @@ fn _slang_getNan() -> f32
}
)";
-void WGSLSourceEmitter::ensurePrelude(const char* preludeText)
-{
- IRStringLit* stringLit;
- if (!m_builtinPreludes.tryGetValue(preludeText, stringLit))
- {
- IRBuilder builder(m_irModule);
- stringLit = builder.getStringValue(UnownedStringSlice(preludeText));
- m_builtinPreludes[preludeText] = stringLit;
- }
- m_requiredPreludes.add(stringLit);
-}
-
void WGSLSourceEmitter::emitSwitchCaseSelectorsImpl(
const SwitchRegion::Case* const currentCase,
const bool isDefault)
diff --git a/source/slang/slang-emit-wgsl.h b/source/slang/slang-emit-wgsl.h
index 28311aa27..390ee876d 100644
--- a/source/slang/slang-emit-wgsl.h
+++ b/source/slang/slang-emit-wgsl.h
@@ -57,10 +57,6 @@ public:
void emit(const AddressSpace addressSpace);
virtual bool shouldFoldInstIntoUseSites(IRInst* inst) SLANG_OVERRIDE;
- Dictionary<const char*, IRStringLit*> m_builtinPreludes;
-
-protected:
- void ensurePrelude(const char* preludeText);
private:
bool maybeEmitSystemSemantic(IRInst* inst);
diff --git a/tests/compute/bitcast-64bit.slang b/tests/compute/bitcast-64bit.slang
new file mode 100644
index 000000000..410fa768a
--- /dev/null
+++ b/tests/compute/bitcast-64bit.slang
@@ -0,0 +1,43 @@
+//TEST(compute):COMPARE_COMPUTE_EX:-vk -compute -shaderobj -emit-spirv-via-glsl -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-vk -compute -shaderobj -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -d3d12 -profile cs_6_6 -use-dxil -shaderobj -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-cuda -compute -shaderobj -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -shaderobj -output-using-type
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0], stride=4):out,name=gOutputBuffer
+RWStructuredBuffer<uint64_t> gOutputBuffer;
+
+int64_t icast(double x)
+{
+ return bit_cast<int64_t>(x);
+}
+
+int64_t icast(uint64_t x)
+{
+ return bit_cast<int64_t>(x);
+}
+
+uint64_t ucast(double x)
+{
+ return bit_cast<uint64_t>(x);
+}
+
+uint64_t ucast(int64_t x)
+{
+ return bit_cast<uint64_t>(x);
+}
+
+[numthreads(1, 1, 1)]
+[shader("compute")]
+void computeMain()
+{
+ double t1 = -1.0;
+ uint64_t t2 = 2;
+ gOutputBuffer[0] = icast(t1); // 0xBFF0000000000000 => 13830554455654793216
+ gOutputBuffer[1] = icast(t2); // 0x0000000000000002 => 2
+
+ double t3 = 3.0;
+ int64_t t4 = -4;
+ gOutputBuffer[2] = ucast(t3); // 0x4008000000000000 => 4613937818241073152
+ gOutputBuffer[3] = ucast(t4); // 0xFFFFFFFFFFFFFFFC => 18446744073709551612
+}
diff --git a/tests/compute/bitcast-64bit.slang.expected.txt b/tests/compute/bitcast-64bit.slang.expected.txt
new file mode 100644
index 000000000..cb9a9f87d
--- /dev/null
+++ b/tests/compute/bitcast-64bit.slang.expected.txt
@@ -0,0 +1,5 @@
+type: uint64_t
+13830554455654793216
+2
+4613937818241073152
+18446744073709551612