[SPIR-V] Feature request: add annotations for images readonly, writeonly
Currently in spirv backend, Texture objects are always translated to sampled image. OpTypeImage will have sampled set to "will be used with sampler" (https://www.khronos.org/registry/SPIR-V/specs/1.0/SPIRV.html#OpTypeImage).
There are many cases where we want to use readonly Texture without sampling (e.g. the format does not support sampling - for example uint64). In this case we want it to be a readonly storage image and GLSL provides correct decorations to do that:
// 1.comp
// glslangValidator -H -V -o 1.spv 1.comp
#version 450
layout(set = 0, binding = 0, rgba8) uniform highp readonly image2D image0;
layout(set = 0, binding = 1, rgba8) uniform highp writeonly image2D image1;
void main() {
vec4 pixel = imageLoad(image0, ivec2(gl_LocalInvocationID));
imageStore(image1, ivec2(gl_LocalInvocationID), pixel);
}
The result contains "NonWritable" and "NonReadable":
Decorate 12(image0) DescriptorSet 0
Decorate 12(image0) Binding 0
Decorate 12(image0) NonWritable
Decorate 17(gl_LocalInvocationID) BuiltIn LocalInvocationId
Decorate 27(image1) DescriptorSet 0
Decorate 27(image1) Binding 1
Decorate 27(image1) NonReadable
Using HLSL with Vulkan makes it difficult to handle these cases, because read-only images will still be treated as UAVs but we want them to be SRVs.
Somewhat related discussion: https://github.com/KhronosGroup/SPIRV-Cross/issues/1306
To illustrate the problem, let me provide a more detailed use case.
Consider the following HLSL shader, which is pretty much identical to GLSL sample above:
// 1.hlsl
Texture2D<uint64_t> image0 : register(t0, space0);
RWTexture2D<uint64_t> image1 : register(u0, space0);
[numthreads (16, 16, 1)]
void main(uint3 dispatchThreadId : SV_DispatchThreadID) {
uint64_t pixel = image0[dispatchThreadId.xy];
image1[dispatchThreadId.xy] = pixel;
}
Here we are using uint64_t format, which does not support sampling. On DirectX 12, we can use SRV descriptor for image0.
For Vulkan, DXC spirv codegen will generate "sampled image" for image0 and reflection tools (e.g. spirv_reflect) will treat it as SRV and descriptor type DESCRIPTOR_TYPE_SAMPLED_IMAGE. What we really want is SRV and DESCRIPTOR_TYPE_STORAGE_IMAGE. The only way to make it work is to change image0 to RWTexture2D, which will result in it being an UAV now (and register specification must change as well).
I believe providing "readony", "writeonly" annotations and emitting corresponding decorations would make it easy to tools to correctly map to Vulkan descriptor types.
Hi @sudonatalie @kuhar! SPIRV bug for you