Skip to content

Commit 68dedee

Browse files
authored
[SPIRV] Add option to use the Unknown image format (#7632)
Many Vulkan driver allow the SPIR-V to use the `Unknown` image format for storage images and texel buffers. This makes the SPIR-V more flexible, and it useful for developers. However, it can be cumbersome to have to add the `vk::image_format` attribute to all resources. This option allows users to make `Unkown` the default image format for all resource types. Fixes #7484
1 parent 4efa3dc commit 68dedee

File tree

9 files changed

+237
-136
lines changed

9 files changed

+237
-136
lines changed

docs/SPIR-V.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,13 @@ are translated into SPIR-V ``OpTypeImage``, with parameters:
896896
The meanings of the headers in the above table is explained in ``OpTypeImage``
897897
of the SPIR-V spec.
898898

899+
For storage images (e.g. ``RWTexture2D<T>``) and texel buffers (e.g. ``RWBuffer<T>``),
900+
the image format is typically inferred from the data type ``T``. However, the
901+
``-fspv-use-unknown-image-format`` command-line option can be used to change
902+
this behavior. When this option is active, the default format for these
903+
resources becomes ``Unknown`` if not otherwise specified by the
904+
``[[vk::image_format]]`` attribute.
905+
899906
Vulkan specific Image Formats
900907
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
901908

include/dxc/Support/HLSLOptions.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,12 @@ def fspv_enable_maximal_reconvergence: Flag<["-"], "fspv-enable-maximal-reconver
403403
HelpText<"Enables the MaximallyReconvergesKHR execution mode for this module.">;
404404
def fspv_use_vulkan_memory_model: Flag<["-"], "fspv-use-vulkan-memory-model">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
405405
HelpText<"Generates SPIR-V modules that use the Vulkan memory model instead of GLSL450.">;
406+
def fspv_use_unknown_image_format
407+
: Flag<["-"], "fspv-use-unknown-image-format">,
408+
Group<spirv_Group>,
409+
Flags<[CoreOption, DriverOption]>,
410+
HelpText<"For storage images and texel buffers, sets the default format to 'Unknown' when not specified via the `vk::image_format` attribute. If this option is not used, the format is inferred from the resource's data type.">;
411+
406412
def fvk_auto_shift_bindings: Flag<["-"], "fvk-auto-shift-bindings">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
407413
HelpText<"Apply fvk-*-shift to resources without an explicit register assignment.">;
408414
def Wno_vk_ignored_features : Joined<["-"], "Wno-vk-ignored-features">, Group<spirv_Group>, Flags<[CoreOption, DriverOption, HelpHidden]>,

include/dxc/Support/SPIRVOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct SpirvCodeGenOptions {
7171
bool fixFuncCallArguments;
7272
bool enableMaximalReconvergence;
7373
bool useVulkanMemoryModel;
74+
bool useUnknownImageFormat;
7475
bool IEEEStrict;
7576
/// Maximum length in words for the OpString literal containing the shader
7677
/// source for DebugSource and DebugSourceContinued. If the source code length

lib/DxcSupport/HLSLOptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
11201120
Args.hasFlag(OPT_fspv_enable_maximal_reconvergence, OPT_INVALID, false);
11211121
opts.SpirvOptions.useVulkanMemoryModel =
11221122
Args.hasFlag(OPT_fspv_use_vulkan_memory_model, OPT_INVALID, false);
1123+
opts.SpirvOptions.useUnknownImageFormat =
1124+
Args.hasFlag(OPT_fspv_use_unknown_image_format, OPT_INVALID, false);
11231125

11241126
if (!handleVkShiftArgs(Args, OPT_fvk_b_shift, "b", &opts.SpirvOptions.bShift,
11251127
errors) ||

tools/clang/lib/SPIRV/LowerTypeVisitor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,10 @@ LowerTypeVisitor::lowerStructFields(const RecordDecl *decl,
11561156
spv::ImageFormat
11571157
LowerTypeVisitor::translateSampledTypeToImageFormat(QualType sampledType,
11581158
SourceLocation srcLoc) {
1159+
1160+
if (spvOptions.useUnknownImageFormat)
1161+
return spv::ImageFormat::Unknown;
1162+
11591163
uint32_t elemCount = 1;
11601164
QualType ty = {};
11611165
if (!isScalarType(sampledType, &ty) &&

tools/clang/test/CodeGenSPIRV/type.buffer.hlsl

Lines changed: 103 additions & 68 deletions
Large diffs are not rendered by default.
Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,80 @@
1-
// RUN: %dxc -T ps_6_6 -E main -fcgl %s -spirv | FileCheck %s
1+
// RUN: %dxc -T ps_6_6 -E main -fcgl %s -spirv | FileCheck %s --check-prefixes=CHECK,INFER
2+
// RUN: %dxc -fspv-use-unknown-image-format -T ps_6_6 -E main -fcgl %s -spirv | FileCheck %s --check-prefixes=CHECK,UNKNOWN
3+
4+
// Before vulkan1.3, we should be trying to infer the image type for because
5+
// we cannot necessarily use Unknown. However in VK1.3 and later, we can use
6+
// Unknown.
27

38
// CHECK: OpCapability SampledBuffer
4-
// CHECK: OpCapability StorageImageExtendedFormats
9+
// INFER: OpCapability StorageImageExtendedFormats
510

6-
// CHECK: %type_buffer_image = OpTypeImage %int Buffer 2 0 0 2 R32i
11+
// INFER: %type_buffer_image = OpTypeImage %int Buffer 2 0 0 2 R32i
12+
// UNKNOWN: %type_buffer_image = OpTypeImage %int Buffer 2 0 0 2 Unknown
713
// CHECK: %_ptr_UniformConstant_type_buffer_image = OpTypePointer UniformConstant %type_buffer_image
814
RasterizerOrderedBuffer<int> introvbuf;
9-
// CHECK: %type_buffer_image_0 = OpTypeImage %uint Buffer 2 0 0 2 R32ui
15+
// INFER: %type_buffer_image_0 = OpTypeImage %uint Buffer 2 0 0 2 R32ui
16+
// UNKNOWN: %type_buffer_image_0 = OpTypeImage %uint Buffer 2 0 0 2 Unknown
1017
// CHECK: %_ptr_UniformConstant_type_buffer_image_0 = OpTypePointer UniformConstant %type_buffer_image_0
1118
RasterizerOrderedBuffer<uint> uintrovbuf;
12-
// CHECK: %type_buffer_image_1 = OpTypeImage %float Buffer 2 0 0 2 R32f
19+
// INFER: %type_buffer_image_1 = OpTypeImage %float Buffer 2 0 0 2 R32f
20+
// UNKNOWN: %type_buffer_image_1 = OpTypeImage %float Buffer 2 0 0 2 Unknown
1321
// CHECK: %_ptr_UniformConstant_type_buffer_image_1 = OpTypePointer UniformConstant %type_buffer_image_1
1422
RasterizerOrderedBuffer<float> floatrovbuf;
1523

16-
// CHECK: %type_buffer_image_2 = OpTypeImage %int Buffer 2 0 0 2 Rg32i
17-
// CHECK: %_ptr_UniformConstant_type_buffer_image_2 = OpTypePointer UniformConstant %type_buffer_image_2
24+
// INFER: %type_buffer_image_2 = OpTypeImage %int Buffer 2 0 0 2 Rg32i
25+
// INFER: %_ptr_UniformConstant_type_buffer_image_2 = OpTypePointer UniformConstant %type_buffer_image_2
1826
RasterizerOrderedBuffer<int2> int2rovbuf;
19-
// CHECK: %type_buffer_image_3 = OpTypeImage %uint Buffer 2 0 0 2 Rg32ui
20-
// CHECK: %_ptr_UniformConstant_type_buffer_image_3 = OpTypePointer UniformConstant %type_buffer_image_3
27+
// INFER: %type_buffer_image_3 = OpTypeImage %uint Buffer 2 0 0 2 Rg32ui
28+
// INFER: %_ptr_UniformConstant_type_buffer_image_3 = OpTypePointer UniformConstant %type_buffer_image_3
2129
RasterizerOrderedBuffer<uint2> uint2rovbuf;
22-
// CHECK: %type_buffer_image_4 = OpTypeImage %float Buffer 2 0 0 2 Rg32f
23-
// CHECK: %_ptr_UniformConstant_type_buffer_image_4 = OpTypePointer UniformConstant %type_buffer_image_4
30+
// INFER: %type_buffer_image_4 = OpTypeImage %float Buffer 2 0 0 2 Rg32f
31+
// INFER: %_ptr_UniformConstant_type_buffer_image_4 = OpTypePointer UniformConstant %type_buffer_image_4
2432
RasterizerOrderedBuffer<float2> float2rovbuf;
2533

26-
// CHECK: %type_buffer_image_5 = OpTypeImage %int Buffer 2 0 0 2 Unknown
27-
// CHECK: %_ptr_UniformConstant_type_buffer_image_5 = OpTypePointer UniformConstant %type_buffer_image_5
28-
// CHECK: %type_buffer_image_6 = OpTypeImage %int Buffer 2 0 0 2 Rgba32i
29-
// CHECK: %_ptr_UniformConstant_type_buffer_image_6 = OpTypePointer UniformConstant %type_buffer_image_6
34+
// INFER: %type_buffer_image_5 = OpTypeImage %int Buffer 2 0 0 2 Unknown
35+
// INFER: %_ptr_UniformConstant_type_buffer_image_5 = OpTypePointer UniformConstant %type_buffer_image_5
36+
// INFER: %type_buffer_image_6 = OpTypeImage %int Buffer 2 0 0 2 Rgba32i
37+
// INFER: %_ptr_UniformConstant_type_buffer_image_6 = OpTypePointer UniformConstant %type_buffer_image_6
3038
RasterizerOrderedBuffer<int3> int3rovbuf;
3139
RasterizerOrderedBuffer<int4> int4rovbuf;
32-
// CHECK: %type_buffer_image_7 = OpTypeImage %uint Buffer 2 0 0 2 Unknown
33-
// CHECK: %_ptr_UniformConstant_type_buffer_image_7 = OpTypePointer UniformConstant %type_buffer_image_7
34-
// CHECK: %type_buffer_image_8 = OpTypeImage %uint Buffer 2 0 0 2 Rgba32ui
35-
// CHECK: %_ptr_UniformConstant_type_buffer_image_8 = OpTypePointer UniformConstant %type_buffer_image_8
40+
// INFER: %type_buffer_image_7 = OpTypeImage %uint Buffer 2 0 0 2 Unknown
41+
// INFER: %_ptr_UniformConstant_type_buffer_image_7 = OpTypePointer UniformConstant %type_buffer_image_7
42+
// INFER: %type_buffer_image_8 = OpTypeImage %uint Buffer 2 0 0 2 Rgba32ui
43+
// INFER: %_ptr_UniformConstant_type_buffer_image_8 = OpTypePointer UniformConstant %type_buffer_image_8
3644
RasterizerOrderedBuffer<uint3> uint3rovbuf;
3745
RasterizerOrderedBuffer<uint4> uint4rovbuf;
38-
// CHECK: %type_buffer_image_9 = OpTypeImage %float Buffer 2 0 0 2 Unknown
39-
// CHECK: %_ptr_UniformConstant_type_buffer_image_9 = OpTypePointer UniformConstant %type_buffer_image_9
40-
// CHECK: %type_buffer_image_10 = OpTypeImage %float Buffer 2 0 0 2 Rgba32f
41-
// CHECK: %_ptr_UniformConstant_type_buffer_image_10 = OpTypePointer UniformConstant %type_buffer_image_10
46+
// INFER: %type_buffer_image_9 = OpTypeImage %float Buffer 2 0 0 2 Unknown
47+
// INFER: %_ptr_UniformConstant_type_buffer_image_9 = OpTypePointer UniformConstant %type_buffer_image_9
48+
// INFER: %type_buffer_image_10 = OpTypeImage %float Buffer 2 0 0 2 Rgba32f
49+
// INFER: %_ptr_UniformConstant_type_buffer_image_10 = OpTypePointer UniformConstant %type_buffer_image_10
4250
RasterizerOrderedBuffer<float3> float3rovbuf;
4351
RasterizerOrderedBuffer<float4> float4rovbuf;
4452

45-
// CHECK: %introvbuf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
46-
// CHECK: %uintrovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_0 UniformConstant
47-
// CHECK: %floatrovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_1 UniformConstant
48-
// CHECK: %int2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_2 UniformConstant
49-
// CHECK: %uint2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_3 UniformConstant
50-
// CHECK: %float2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_4 UniformConstant
51-
// CHECK: %int3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_5 UniformConstant
52-
// CHECK: %int4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_6 UniformConstant
53-
// CHECK: %uint3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_7 UniformConstant
54-
// CHECK: %uint4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_8 UniformConstant
55-
// CHECK: %float3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_9 UniformConstant
56-
// CHECK: %float4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_10 UniformConstant
53+
// INFER: %introvbuf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
54+
// INFER: %uintrovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_0 UniformConstant
55+
// INFER: %floatrovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_1 UniformConstant
56+
// INFER: %int2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_2 UniformConstant
57+
// INFER: %uint2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_3 UniformConstant
58+
// INFER: %float2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_4 UniformConstant
59+
// INFER: %int3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_5 UniformConstant
60+
// INFER: %int4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_6 UniformConstant
61+
// INFER: %uint3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_7 UniformConstant
62+
// INFER: %uint4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_8 UniformConstant
63+
// INFER: %float3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_9 UniformConstant
64+
// INFER: %float4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_10 UniformConstant
65+
66+
// UNKNOWN: %introvbuf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
67+
// UNKNOWN: %uintrovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_0 UniformConstant
68+
// UNKNOWN: %floatrovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_1 UniformConstant
69+
// UNKNOWN: %int2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
70+
// UNKNOWN: %uint2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_0 UniformConstant
71+
// UNKNOWN: %float2rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_1 UniformConstant
72+
// UNKNOWN: %int3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
73+
// UNKNOWN: %int4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
74+
// UNKNOWN: %uint3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_0 UniformConstant
75+
// UNKNOWN: %uint4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_0 UniformConstant
76+
// UNKNOWN: %float3rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_1 UniformConstant
77+
// UNKNOWN: %float4rovbuf = OpVariable %_ptr_UniformConstant_type_buffer_image_1 UniformConstant
5778

5879
void main() {}
5980

tools/clang/test/CodeGenSPIRV/type.rasterizer-ordered-texture.hlsl

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
1-
// RUN: %dxc -T ps_6_6 -E main -fcgl %s -spirv | FileCheck %s
1+
// RUN: %dxc -T ps_6_6 -E main -fcgl %s -spirv | FileCheck %s --check-prefixes=CHECK,INFER
2+
// RUN: %dxc -fspv-use-unknown-image-format -T ps_6_6 -E main -fcgl %s -spirv | FileCheck %s --check-prefixes=CHECK,UNKNOWN
23

34
// CHECK: OpCapability Image1D
45

5-
// CHECK: %type_1d_image = OpTypeImage %int 1D 2 0 0 2 R32i
6+
// INFER: %type_1d_image = OpTypeImage %int 1D 2 0 0 2 R32i
7+
// UNKNOWN: %type_1d_image = OpTypeImage %int 1D 2 0 0 2 Unknown
68
// CHECK: %_ptr_UniformConstant_type_1d_image = OpTypePointer UniformConstant %type_1d_image
7-
// CHECK: %type_2d_image = OpTypeImage %uint 2D 2 0 0 2 Rg32ui
9+
// INFER: %type_2d_image = OpTypeImage %uint 2D 2 0 0 2 Rg32ui
10+
// UNKNOWN: %type_2d_image = OpTypeImage %uint 2D 2 0 0 2 Unknown
811
// CHECK: %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
9-
// CHECK: %type_3d_image = OpTypeImage %int 3D 2 0 0 2 R32i
12+
// INFER: %type_3d_image = OpTypeImage %int 3D 2 0 0 2 R32i
13+
// UNKNOWN: %type_3d_image = OpTypeImage %int 3D 2 0 0 2 Unknown
1014
// CHECK: %_ptr_UniformConstant_type_3d_image = OpTypePointer UniformConstant %type_3d_image
11-
// CHECK: %type_3d_image_0 = OpTypeImage %float 3D 2 0 0 2 Rgba32f
12-
// CHECK: %_ptr_UniformConstant_type_3d_image_0 = OpTypePointer UniformConstant %type_3d_image_0
13-
// CHECK: %type_1d_image_array = OpTypeImage %int 1D 2 1 0 2 R32i
14-
// CHECK: %_ptr_UniformConstant_type_1d_image_array = OpTypePointer UniformConstant %type_1d_image_array
15-
// CHECK: %type_2d_image_array = OpTypeImage %uint 2D 2 1 0 2 Rg32ui
16-
// CHECK: %_ptr_UniformConstant_type_2d_image_array = OpTypePointer UniformConstant %type_2d_image_array
17-
// CHECK: %type_1d_image_array_0 = OpTypeImage %float 1D 2 1 0 2 Rgba32f
18-
// CHECK: %_ptr_UniformConstant_type_1d_image_array_0 = OpTypePointer UniformConstant %type_1d_image_array_0
19-
// CHECK: %type_2d_image_array_0 = OpTypeImage %float 2D 2 1 0 2 Rgba32f
20-
// CHECK: %_ptr_UniformConstant_type_2d_image_array_0 = OpTypePointer UniformConstant %type_2d_image_array_0
15+
// INFER: %type_3d_image_0 = OpTypeImage %float 3D 2 0 0 2 Rgba32f
16+
// INFER: %_ptr_UniformConstant_type_3d_image_0 = OpTypePointer UniformConstant %type_3d_image_0
17+
// INFER: %type_1d_image_array = OpTypeImage %int 1D 2 1 0 2 R32i
18+
// INFER: %_ptr_UniformConstant_type_1d_image_array = OpTypePointer UniformConstant %type_1d_image_array
19+
// INFER: %type_2d_image_array = OpTypeImage %uint 2D 2 1 0 2 Rg32ui
20+
// INFER: %_ptr_UniformConstant_type_2d_image_array = OpTypePointer UniformConstant %type_2d_image_array
21+
// INFER: %type_1d_image_array_0 = OpTypeImage %float 1D 2 1 0 2 Rgba32f
22+
// INFER: %_ptr_UniformConstant_type_1d_image_array_0 = OpTypePointer UniformConstant %type_1d_image_array_0
23+
// INFER: %type_2d_image_array_0 = OpTypeImage %float 2D 2 1 0 2 Rgba32f
24+
// INFER: %_ptr_UniformConstant_type_2d_image_array_0 = OpTypePointer UniformConstant %type_2d_image_array_0
2125

2226

2327
// CHECK: %t1 = OpVariable %_ptr_UniformConstant_type_1d_image UniformConstant
@@ -33,7 +37,8 @@ RasterizerOrderedTexture3D <int> t3 ;
3337
[[vk::image_format("rgba32f")]]
3438
RasterizerOrderedTexture3D <float3> t4 ;
3539

36-
// CHECK: %t5 = OpVariable %_ptr_UniformConstant_type_3d_image_0 UniformConstant
40+
// INFER: %t5 = OpVariable %_ptr_UniformConstant_type_3d_image_0 UniformConstant
41+
// UNKNOWN: %t5 = OpVariable %_ptr_UniformConstant_type_3d_image_1 UniformConstant
3742
RasterizerOrderedTexture3D <float4> t5 ;
3843

3944
// CHECK: %t6 = OpVariable %_ptr_UniformConstant_type_1d_image_array UniformConstant

0 commit comments

Comments
 (0)