KhronosGroup / glslang

Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator.
Other
2.9k stars 816 forks source link

OpExecutionModeId not used unless targeting SPIRV-1.6 #3510

Open castano opened 4 months ago

castano commented 4 months ago

It appears that OpExecutionModeId was introduced in SPIR-V 1.2. However, it is not used unless we target SPIR-V 1.6.

Here's a minimal example:

#version 450
layout (constant_id = 0) const uint local_size_x = 128;
layout (local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
void main() {}

When compiled with:

glslangValidator.exe -V100 --target-env spirv1.2  -e main repro.comp.glsl -o spirv/repro.comp.spv

It produces:

; SPIR-V
; Version: 1.2
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 12
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %main "main"
               OpExecutionMode %main LocalSize 1 1 1
               OpSource GLSL 450
               OpName %main "main"
               OpName %local_size_x "local_size_x"
               OpDecorate %local_size_x SpecId 0
               OpDecorate %8 SpecId 0
               OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
       %uint = OpTypeInt 32 0
%local_size_x = OpSpecConstant %uint 128
          %8 = OpSpecConstant %uint 1
     %uint_1 = OpConstant %uint 1
     %v3uint = OpTypeVector %uint 3
%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %8 %uint_1 %uint_1
       %main = OpFunction %void None %3
          %5 = OpLabel
               OpReturn
               OpFunctionEnd

But when compiled with:

glslangValidator.exe -V100 --target-env spirv1.6  -e main repro.comp.glsl -o spirv/repro.comp.spv

Produces:

; SPIR-V
; Version: 1.6
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 13
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %main "main"
               OpExecutionModeId %main LocalSizeId %7 %uint_1 %uint_1
               OpSource GLSL 450
               OpName %main "main"
               OpName %local_size_x "local_size_x"
               OpDecorate %7 SpecId 0
               OpDecorate %local_size_x SpecId 0
               OpDecorate %10 SpecId 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
       %uint = OpTypeInt 32 0
          %7 = OpSpecConstant %uint 1
     %uint_1 = OpConstant %uint 1
%local_size_x = OpSpecConstant %uint 128
         %10 = OpSpecConstant %uint 1
     %v3uint = OpTypeVector %uint 3
         %12 = OpSpecConstantComposite %v3uint %10 %uint_1 %uint_1
       %main = OpFunction %void None %3
          %5 = OpLabel
               OpReturn
               OpFunctionEnd

Is the code produced in the first case valid? ExecutionMode is configured as (1, 1, 1), but gl_WorkGroupSize is then defined according to the specialization constants. Is that correct?

If not, should the use of local_size_x_id be an error when targeting spir-v versions prior to 1.2?