intel / intel/llvm

Invalid SPIR-V for image sampling ops and spec/model mismatch for non-sampled reads

Open
#21,366 6 comments 0 reactions 0 assignees View on GitHub
bug confirmed
Dominant language
LLVM
Stars
1.5k
Forks
854
Avg merge
3d 17h
Merged PRs (30d)
137

Description

## Generated Image Sample/Fetch SPIR-V is invalid
DPC++ emits `OpImageSample*` (or other related sampling ops) with a result type that is not a 4-component vector, which violates SPIR-V validity rules for sampling instructions. For example, the spec for `OpImageSampleExplicitLod` states

> Result Type must be a vector of four components of [floating-point type](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Floating) or [integer type](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Integer)

Compile any bindless sampled image test which uses non-4-component vector returns, such as `sampling_1D.cpp` and run the generated SPIR-V through the spirv validator:
```cpp
> spirv-val.exe sycl_spir64.spv
error: line 156: Expected Result Type to be int or float vector type
%call1_i_i_i = OpImageSampleExplicitLod %float %call_i_i %div_i_i Lod %float_0
```

This can be fixed in DPC++ pretty simply and I have a patch for this which I can post a PR for soon.

## Spec/model mismatch
SPIR-V allows `OpImageRead` / non-sampling reads to return either a scalar or a vector of various widths. In contrast, OpenCL's built-in image read functions always return 4-component vectors. This is not necessarily invalid SPIR-V by itself, however, when targeting the OpenCL execution environment, additional constraints may demand the enforcement of OpenCL-style vector widths.

It would be helpful to clarify whether DPC++ intends to strictly follow OpenCL's image semantics in its SPIR-V lowering, or whether narrower result types are considered acceptable under the OpenCL execution environment.

### Example: SPIRV-LLVM-Translator behavior under OpenCL semantics

For an example of the trade-off between strictly following the SPIR-V specification and targeting OpenCL image semantics, we can examine the behavior of the upstream SPIRV-LLVM-Translator. When provided with the SPIR-V module generated by the `read_write_unsampled.cpp` test using the command-line invocation:

```cpp
llvm-spirv --spirv-target-env CL2.0 -r read_write_unsampled.spv -o read_write_unsampled.bc
```
the resulting LLVM bitcode is malformed.

This occurs due to an implicit assumption in the SPIR-V–to–OpenCL translation that `OpImageRead` always returns a four-component vector. When this assumption is violated, name mangling and signature mismatches occur, resulting in function definitions being incorrectly overwritten in the generated LLVM IR.

Thanks to @AdamBrouwersHarries for pointing the above out!

Tagging @bashbaug for his opinion👋, thanks!

### Environment

- OS: N/A
- Target device and vendor: N/A
- DPC++ version: clang version 21.0.0
- Dependencies version: N/A

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.