microsoft / microsoft/DirectXShaderCompiler
[SPIR-V] Intrinsics returning `vk::SpirvOpaqueType</*spv::OpTypePointer*/32,` don't codegen properly
@luciechoi is already working on this.
Since Apr 2, 2026.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
Description
DXC gets mightly confused by Inline SpirV intrinsics.
@s-perron this will probably spoil your fun with Workgroup storage class pointers.
Steps to Reproduce
If we make no temporary image_ptr_t like so it works : https://godbolt.org/z/sEGKrGaao
template<typename T, int32_t Dim, typename ImgT>
[[vk::ext_instruction(/*spv::OpImageTexelPointer*/60)]]
T imageTexelPointer([[vk::ext_reference]] ImgT Image, vector<uint32_t,Dim> coord, uint32_t sample);
...
spirv::atomicFAddEXT(spirv::imageTexelPointer<float32_t>(velImgF32,coord,0),/*spv::ScopeDevice*/1,/*spv::MemorySemanticsMaskNone*/0,val);
However if we try to make the intrinsic actually return a Spir-V pointer type we run into trouble https://godbolt.org/z/bjjGo5xGM
template<typename T, int32_t Dim, typename ImgT>
[[vk::ext_instruction(/*spv::OpImageTexelPointer*/60)]]
image_ptr_t<T> imageTexelPointer([[vk::ext_reference]] ImgT Image, vector<uint32_t,Dim> coord, uint32_t sample);
...
spirv::image_ptr_t<float32_t> pTexel = spirv::imageTexelPointer<float32_t>(velImgF32,coord,0);
spirv::atomicFAddEXT(pTexel,/*spv::ScopeDevice*/1,/*spv::MemorySemanticsMaskNone*/0,val);
Actual Behavior
Insight provided by -Vd https://godbolt.org/z/4z44joGqE
spirv::imageTexelPointer<float32_t>(velImgF32,coord,0);
generates
%20 = OpImageTexelPointer %_ptr_Image__ptr_Image_float %velImgF32 %19 %uint_0
But what is _ptr_Image__ptr_Image_float you might ask?
%_ptr_Image_float = OpTypePointer Image %float
%_ptr_Image__ptr_Image_float = OpTypePointer Image %_ptr_Image_float
Pointer of Image Storage class to Pointer of Image Storage Class!
The compiler seems to expect that the Inline SPIRV intrinsic always return a non-SPIR-V type T which is supposed to be a variable, so the SPIR-V codegen makes a "pointer to T" declaration.
Its because it slaps an extra layer of pointer on your return type, thats why it worked for the above original "wrong" return type of "just" T. Frankly I am amazed it guessed the storage class right.
This is obviously wrong for an intrinsic you'd want to return an actual SPIR-V pointer. Why would you want to return an inline SPIR-V pointer? Because you don't want DXC's codegen to guess the storage class for you / be in control!
Example: velImgF32 is a Function Storage Class pointer of OpTypeImage %float 3D 2 0 0 2 R32f type, and OpImageTexelPointer produces an Image Storage Class pointer to float out of it.
Environment
- DXC version: Godbolt trunk
- Host Operating System <!--- Host operating system and version --->
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.