diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index f465fdd323..eeb990d3ef 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -26032,6 +26032,7 @@ struct DescriptorHandle : IComparable /// Constructor for uint64_t handles [ForceInline] [require(spvBindlessTextureNV)] + [require(cuda)] __intrinsic_op($(kIROp_CastUInt64ToDescriptorHandle)) __init(uint64_t handleValue); @@ -26041,6 +26042,7 @@ struct DescriptorHandle : IComparable __target_switch { case spvBindlessTextureNV: + case cuda: return (uint64_t)this == (uint64_t)other; default: return all(__vectorEql((uint2)this, (uint2)other)); @@ -26053,6 +26055,7 @@ struct DescriptorHandle : IComparable __target_switch { case spvBindlessTextureNV: + case cuda: return (uint64_t)this < (uint64_t)other; default: let vthis = ((uint2)this); @@ -26067,6 +26070,7 @@ struct DescriptorHandle : IComparable __target_switch { case spvBindlessTextureNV: + case cuda: return (uint64_t)this <= (uint64_t)other; default: let vthis = ((uint2)this); @@ -26089,6 +26093,7 @@ extension uint64_t { __intrinsic_op($(kIROp_CastDescriptorHandleToUInt64)) [require(spvBindlessTextureNV)] + [require(cuda)] __init(DescriptorHandle bindless); } diff --git a/tests/language-feature/descriptor-handle/desc-handle-cuda-uint64.slang b/tests/language-feature/descriptor-handle/desc-handle-cuda-uint64.slang new file mode 100644 index 0000000000..86321cc4a2 --- /dev/null +++ b/tests/language-feature/descriptor-handle/desc-handle-cuda-uint64.slang @@ -0,0 +1,58 @@ +//TEST:SIMPLE(filecheck=CUDA): -target cuda -entry computeMain -stage compute + +// Test that DescriptorHandle can be constructed from uint64_t in CUDA. +// In CUDA, DescriptorHandle becomes transparent and maps directly to the underlying +// resource type (CUtexObject/CUsurfObject which are ulonglong). This means: +// 1. uint64_t -> DescriptorHandle conversion is a no-op cast +// 2. DescriptorHandle -> uint64_t conversion is a no-op cast +// 3. Comparison methods (equals, lessThan, etc.) cannot be called directly because +// the handle type is erased to the resource type at compile time. + +// CUDA-DAG: ulonglong textureHandle +// CUDA-DAG: tex2DLod +// CUDA-DAG: void computeMain + +uniform uint64_t textureHandle; +uniform uint64_t textureHandle2; + +// Cast uint64_t to DescriptorHandle and use it +DescriptorHandle getTextureHandle(uint64_t h) +{ + return DescriptorHandle(h); +} + +// Cast DescriptorHandle to uint64_t +uint64_t getHandleValue(DescriptorHandle h) +{ + return (uint64_t)h; +} + +// Test that we can compare handles using uint64_t comparisons +// (since direct method calls aren't available in CUDA) +bool compareHandles(uint64_t h1, uint64_t h2) +{ + DescriptorHandle handle1 = DescriptorHandle(h1); + DescriptorHandle handle2 = DescriptorHandle(h2); + // Convert back to uint64_t for comparison + return (uint64_t)handle1 == (uint64_t)handle2; +} + +uniform RWStructuredBuffer output; + +[numthreads(1,1,1)] +void computeMain() +{ + // Test construction from uint64_t - creates a texture handle + DescriptorHandle tex = DescriptorHandle(textureHandle); + + // Test conversion to uint64_t and back + uint64_t handleValue = (uint64_t)tex; + DescriptorHandle tex2 = DescriptorHandle(handleValue); + + // Test comparison via uint64_t conversion + bool same = compareHandles(textureHandle, textureHandle2); + + // Sample the texture using the handle + output[0] = tex->SampleLevel(float2(0.0), 0.0); + output[1] = float4(same ? 1.0 : 0.0, 0.0, 0.0, 0.0); +}