microsoft / microsoft/DirectXShaderCompiler

[SPIR-V] Intrinsics returning `vk::SpirvOpaqueType</*spv::OpTypePointer*/32,` don't codegen properly

Open
#6,978 1 comment 0 reactions 1 assignee View on GitHub

@luciechoi is already working on this.

Since Apr 2, 2026.

bug needs-triage spirv
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.