Invalid SPIR-V for image sampling ops and spec/model mismatch for non-sampled reads
- 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
Assessment
This issue has not been assessed yet.