glslang
glslang copied to clipboard
Precision of image is applied to result of imageLoad when generating SPIR-V
Take the following code:
#version 320 es
layout(set = 0, binding = 0, rgba8) uniform readonly mediump image2D img;
layout(set = 0, binding = 1) buffer B
{
vec4 result;
};
void main()
{
result = imageLoad(img, ivec2(0));
}
It produces the following SPIR-V:
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 10
; Bound: 22
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource ESSL 320
OpName %main "main"
OpName %B "B"
OpMemberName %B 0 "result"
OpName %_ ""
OpName %img "img"
OpMemberDecorate %B 0 Offset 0
OpDecorate %B BufferBlock
OpDecorate %_ DescriptorSet 0
OpDecorate %_ Binding 1
OpDecorate %img RelaxedPrecision
OpDecorate %img DescriptorSet 0
OpDecorate %img Binding 0
OpDecorate %img NonWritable
OpDecorate %16 RelaxedPrecision
OpDecorate %19 RelaxedPrecision
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%B = OpTypeStruct %v4float
%_ptr_Uniform_B = OpTypePointer Uniform %B
%_ = OpVariable %_ptr_Uniform_B Uniform
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%13 = OpTypeImage %float 2D 0 0 0 2 Rgba8
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%img = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v2int = OpTypeVector %int 2
%18 = OpConstantComposite %v2int %int_0 %int_0
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%main = OpFunction %void None %3
%5 = OpLabel
%16 = OpLoad %13 %img
%19 = OpImageRead %v4float %16 %18
%21 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0
OpStore %21 %19
OpReturn
OpFunctionEnd
Note that the image is mediump
. Note also that %19 = OpImageRead ..
is decorated with RelaxedPrecision
. This is incorrect according to the GLSL ES spec which defines imageLoad
as returning a highp
value:
highp gvec4 imageLoad(readonly IMAGE_PARAMS)
This might be a spec issue too, since it definitely makes sense for the precision of the image to apply to the result of imageLoad
.
I think that the glslang behaviour does follow the current spec [1], although the spec itself is a bit weird. The GL working group will resolve what the spec should say in internal issue opengl/GLSL#57, so I would hold off making any changes to glslang until that is resolved.
[1] In the introduction to chapter 8 "Built-In Functions" the spec actually says that texture and image functions always use the precision of the image type, and only other functions look at the explicit qualification of the return type. That leaves this case looking a bit ridiculous.
In the end the spec issue was resolved by clarifying that the precision of the return value of imageRead is the precision of the image. I think this can be closed, as the current behavior matches the spec.