[llvm] [SPIRV] Add StorageImageExtendedFormats to available list for Vulkan (PR #192512)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 11:48:00 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Steven Perron (s-perron)
<details>
<summary>Changes</summary>
Some image formats used in OpTypeImage require the
StorageImageExtendedFormats capability. When it is not in the available
list, it is not emitted, causing invalid SPIR-V.
The solution is to add it to the list. It is available for all versions
of Vulkan.
Fixes #<!-- -->192486
---
Full diff: https://github.com/llvm/llvm-project/pull/192512.diff
7 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+2-1)
- (added) llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatR11fG11fB10f.ll (+23)
- (added) llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32f.ll (+23)
- (added) llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32i.ll (+23)
- (added) llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32ui.ll (+23)
- (added) llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32f.ll (+25)
- (added) llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32ui.ll (+24)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 2eb84dec2cf29..c5d5af3bad238 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -965,7 +965,8 @@ void RequirementHandler::initAvailableCapabilitiesForVulkan(
Capability::StorageImageArrayDynamicIndexing,
Capability::DerivativeControl, Capability::MinLod,
Capability::ImageQuery, Capability::ImageGatherExtended,
- Capability::Addresses, Capability::VulkanMemoryModelKHR});
+ Capability::Addresses, Capability::VulkanMemoryModelKHR,
+ Capability::StorageImageExtendedFormats});
// Became core in Vulkan 1.2
if (ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatR11fG11fB10f.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatR11fG11fB10f.ll
new file mode 100644
index 0000000000000..261097256c8f9
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatR11fG11fB10f.ll
@@ -0,0 +1,23 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability StorageImageExtendedFormats
+; CHECK-DAG: %[[#float:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#image:]] = OpTypeImage %[[#float]] Buffer 2 0 0 2 R11fG11fB10f
+; CHECK-DAG: %[[#ptr:]] = OpTypePointer UniformConstant %[[#image]]
+; CHECK-DAG: %[[#var:]] = OpVariable %[[#ptr]] UniformConstant
+
+ at .str = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+define void @main() #0 {
+ %buffer = call target("spirv.Image", float, 5, 2, 0, 0, 2, 8)
+ @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_8(
+ i32 16, i32 7, i32 1, i32 0, ptr nonnull @.str)
+ %data = call <4 x float> @llvm.spv.resource.load.typedbuffer(
+ target("spirv.Image", float, 5, 2, 0, 0, 2, 8) %buffer, i32 0)
+ ret void
+}
+
+declare <4 x float> @llvm.spv.resource.load.typedbuffer(target("spirv.Image", float, 5, 2, 0, 0, 2, 8), i32)
+
+attributes #0 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32f.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32f.ll
new file mode 100644
index 0000000000000..94e53e1f53844
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32f.ll
@@ -0,0 +1,23 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability StorageImageExtendedFormats
+; CHECK-DAG: %[[#float:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#image:]] = OpTypeImage %[[#float]] Buffer 2 0 0 2 Rg32f
+; CHECK-DAG: %[[#ptr:]] = OpTypePointer UniformConstant %[[#image]]
+; CHECK-DAG: %[[#var:]] = OpVariable %[[#ptr]] UniformConstant
+
+ at .str = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+define void @main() #0 {
+ %buffer = call target("spirv.Image", float, 5, 2, 0, 0, 2, 6)
+ @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_6(
+ i32 16, i32 7, i32 1, i32 0, ptr nonnull @.str)
+ %data = call <4 x float> @llvm.spv.resource.load.typedbuffer(
+ target("spirv.Image", float, 5, 2, 0, 0, 2, 6) %buffer, i32 0)
+ ret void
+}
+
+declare <4 x float> @llvm.spv.resource.load.typedbuffer(target("spirv.Image", float, 5, 2, 0, 0, 2, 6), i32)
+
+attributes #0 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32i.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32i.ll
new file mode 100644
index 0000000000000..60b19062c09e8
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32i.ll
@@ -0,0 +1,23 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability StorageImageExtendedFormats
+; CHECK-DAG: %[[#int:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#image:]] = OpTypeImage %[[#int]] Buffer 2 0 0 2 Rg32i
+; CHECK-DAG: %[[#ptr:]] = OpTypePointer UniformConstant %[[#image]]
+; CHECK-DAG: %[[#var:]] = OpVariable %[[#ptr]] UniformConstant
+
+ at .str = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+define void @main() #0 {
+ %buffer = call target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 25)
+ @llvm.spv.resource.handlefrombinding.tspirv.SignedImage_i32_5_2_0_0_2_25(
+ i32 16, i32 7, i32 1, i32 0, ptr nonnull @.str)
+ %data = call <4 x i32> @llvm.spv.resource.load.typedbuffer(
+ target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 25) %buffer, i32 0)
+ ret void
+}
+
+declare <4 x i32> @llvm.spv.resource.load.typedbuffer(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 25), i32)
+
+attributes #0 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32ui.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32ui.ll
new file mode 100644
index 0000000000000..7255992230c40
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRg32ui.ll
@@ -0,0 +1,23 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability StorageImageExtendedFormats
+; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#image:]] = OpTypeImage %[[#uint]] Buffer 2 0 0 2 Rg32ui
+; CHECK-DAG: %[[#ptr:]] = OpTypePointer UniformConstant %[[#image]]
+; CHECK-DAG: %[[#var:]] = OpVariable %[[#ptr]] UniformConstant
+
+ at .str = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+define void @main() #0 {
+ %buffer = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 35)
+ @llvm.spv.resource.handlefrombinding.tspirv.Image_i32_5_2_0_0_2_35(
+ i32 16, i32 7, i32 1, i32 0, ptr nonnull @.str)
+ %data = call <4 x i32> @llvm.spv.resource.load.typedbuffer(
+ target("spirv.Image", i32, 5, 2, 0, 0, 2, 35) %buffer, i32 0)
+ ret void
+}
+
+declare <4 x i32> @llvm.spv.resource.load.typedbuffer(target("spirv.Image", i32, 5, 2, 0, 0, 2, 35), i32)
+
+attributes #0 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32f.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32f.ll
new file mode 100644
index 0000000000000..4ad877f450f78
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32f.ll
@@ -0,0 +1,25 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability Shader
+; CHECK-NOT: OpCapability StorageImageExtendedFormats
+; CHECK-DAG: %[[#float:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#image:]] = OpTypeImage %[[#float]] Buffer 2 0 0 2 Rgba32f
+; CHECK-DAG: %[[#ptr:]] = OpTypePointer UniformConstant %[[#image]]
+; CHECK-DAG: %[[#var:]] = OpVariable %[[#ptr]] UniformConstant
+
+ at .str = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+define void @main() #0 {
+ %buffer = call target("spirv.Image", float, 5, 2, 0, 0, 2, 1)
+ @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_1(
+ i32 16, i32 7, i32 1, i32 0, ptr nonnull @.str)
+ %data = call <4 x float> @llvm.spv.resource.load.typedbuffer(
+ target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %buffer, i32 0)
+ ret void
+}
+
+declare <4 x float> @llvm.spv.resource.load.typedbuffer(target("spirv.Image", float, 5, 2, 0, 0, 2, 1), i32)
+
+
+attributes #0 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32ui.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32ui.ll
new file mode 100644
index 0000000000000..24c6a58a49197
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/ImageFormatRgba32ui.ll
@@ -0,0 +1,24 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability Shader
+; CHECK-NOT: OpCapability StorageImageExtendedFormats
+; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#image:]] = OpTypeImage %[[#uint]] Buffer 2 0 0 2 Rgba32ui
+; CHECK-DAG: %[[#ptr:]] = OpTypePointer UniformConstant %[[#image]]
+; CHECK-DAG: %[[#var:]] = OpVariable %[[#ptr]] UniformConstant
+
+ at .str = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+define void @main() #0 {
+ %buffer = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 30)
+ @llvm.spv.resource.handlefrombinding.tspirv.Image_i32_5_2_0_0_2_30(
+ i32 16, i32 7, i32 1, i32 0, ptr nonnull @.str)
+ %data = call <4 x i32> @llvm.spv.resource.load.typedbuffer(
+ target("spirv.Image", i32, 5, 2, 0, 0, 2, 30) %buffer, i32 0)
+ ret void
+}
+
+declare <4 x i32> @llvm.spv.resource.load.typedbuffer(target("spirv.Image", i32, 5, 2, 0, 0, 2, 30), i32)
+
+attributes #0 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
``````````
</details>
https://github.com/llvm/llvm-project/pull/192512
More information about the llvm-commits
mailing list