dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.two_arrays_different_stride_1
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.two_arrays_different_stride_2
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.ubo_to_ssbo
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.ssbo_comparisons_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_ssbo_2_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_ssbo_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_wg_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.wg_comparisons_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.null_comparisons_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.null_comparisons_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.ssbo_comparisons_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_ssbo_2_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_vars_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_vars_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.wg_comparisons_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.null_comparisons_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.null_comparisons_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.ssbo_comparisons_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_ssbo_2_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_vars_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_vars_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.wg_comparisons_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.different_alignments
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.no_source_access_operands
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.no_target_access_operands
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.partially_active_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.subgroup_cfg_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.subgroup_uniform
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.workgroup_cfg_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.workgroup_uniform
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.function_2_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.function_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.private_2_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.private_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_workgroup_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.hlsl_functionality1.counter_buffer
+dEQP-VK.spirv_assembly.instruction.spirv1p4.hlsl_functionality1.decorate_string
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.iteration_multiple
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.max_iterations
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.min_iterations
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.partial_count
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.peel_count
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.scalar_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.struct_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.vector_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_16_64_bit
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_16
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_251658240_64_bits
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_61440
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_16_64_bit
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_16
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_983040
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_zero_extend_n4096
+dEQP-VK.spirv_assembly.instruction.spirv1p4.wrap.no_signed_wrap
+dEQP-VK.spirv_assembly.instruction.spirv1p4.wrap.no_unsigned_wrap
dEQP-VK.spirv_assembly.type.scalar.i8.negate_vert
dEQP-VK.spirv_assembly.type.scalar.i8.negate_tessc
dEQP-VK.spirv_assembly.type.scalar.i8.negate_tesse
# cmake file for amber
+set(AMBER_ENABLE_SHARED_CRT TRUE)
set(AMBER_SKIP_TESTS TRUE)
set(AMBER_SKIP_SPIRV_TOOLS TRUE)
set(AMBER_SKIP_SHADERC TRUE)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Compute shader with push constnat.
+;
+; #version 430
+;
+; layout(push_constant) uniform pushConstants {
+; int in_val;
+; } u_pushConstants;
+;
+; layout(std430, binding = 0) buffer output_buffer
+; {
+; int out_SSBO[];
+; };
+;
+; void main() {
+; out_SSBO[gl_GlobalInvocationID.z] = u_pushConstants.in_val;
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %gl_GlobalInvocationID %u_pushConstants
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+ OpName %pushConstants "pushConstants"
+ OpMemberName %pushConstants 0 "in_val"
+ OpName %u_pushConstants "u_pushConstants"
+ OpDecorate %_runtimearr_int ArrayStride 4
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+ OpMemberDecorate %pushConstants 0 Offset 0
+ OpDecorate %pushConstants Block
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_runtimearr_int = OpTypeRuntimeArray %int
+%output_buffer = OpTypeStruct %_runtimearr_int
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_0 = OpConstant %int 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %uint_2 = OpConstant %uint 2
+%_ptr_Input_uint = OpTypePointer Input %uint
+%pushConstants = OpTypeStruct %int
+%_ptr_PushConstant_pushConstants = OpTypePointer PushConstant %pushConstants
+%u_pushConstants = OpVariable %_ptr_PushConstant_pushConstants PushConstant
+%_ptr_PushConstant_int = OpTypePointer PushConstant %int
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %18 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %19 = OpLoad %uint %18
+ %24 = OpAccessChain %_ptr_PushConstant_int %u_pushConstants %int_0
+ %25 = OpLoad %int %24
+ %27 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0 %19
+ OpStore %27 %25
+ OpReturn
+ OpFunctionEnd
+[test]
+uniform int 0 1
+ssbo 0:0 subdata int 0 -1 -1
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:0 0 == 1 -1
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Compute shader with SSBO input and output.
+; #version 430
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; int data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_SSBO[];
+; };
+;
+; void main() {
+; out_SSBO[gl_GlobalInvocationID.z] = data_SSBO[gl_GlobalInvocationID.z];
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %gl_GlobalInvocationID %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "data_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_int ArrayStride 4
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+ OpDecorate %_runtimearr_int_0 ArrayStride 4
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_runtimearr_int = OpTypeRuntimeArray %int
+%output_buffer = OpTypeStruct %_runtimearr_int
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_0 = OpConstant %int 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %uint_2 = OpConstant %uint 2
+%_ptr_Input_uint = OpTypePointer Input %uint
+%_runtimearr_int_0 = OpTypeRuntimeArray %int
+%input_buffer = OpTypeStruct %_runtimearr_int_0
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %18 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %19 = OpLoad %uint %18
+ %24 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %25 = OpLoad %uint %24
+ %27 = OpAccessChain %_ptr_StorageBuffer_int %__0 %int_0 %25
+ %28 = OpLoad %int %27
+ %29 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0 %19
+ OpStore %29 %28
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:0 subdata int 0 0 1
+ssbo 0:1 subdata int 0 -1 -1
+
+compute entrypoint main
+compute 1 1 2
+
+probe ssbo int 0:1 0 == 0 1
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Compute shader with a UBO.
+;
+; #version 430
+;
+; layout(binding = 0) uniform input_buffer
+; {
+; int in_data[2];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_SSBO[];
+; };
+;
+; void main() {
+; out_SSBO[gl_GlobalInvocationID.z] = in_data[gl_GlobalInvocationID.z];
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %gl_GlobalInvocationID %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_data"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_int ArrayStride 4
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+ OpDecorate %_arr_int_uint_2 ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_runtimearr_int = OpTypeRuntimeArray %int
+%output_buffer = OpTypeStruct %_runtimearr_int
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_0 = OpConstant %int 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %uint_2 = OpConstant %uint 2
+%_ptr_Input_uint = OpTypePointer Input %uint
+%_arr_int_uint_2 = OpTypeArray %int %uint_2
+%input_buffer = OpTypeStruct %_arr_int_uint_2
+%_ptr_Uniform_input_buffer = OpTypePointer Uniform %input_buffer
+ %__0 = OpVariable %_ptr_Uniform_input_buffer Uniform
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %18 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %19 = OpLoad %uint %18
+ %24 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %25 = OpLoad %uint %24
+ %27 = OpAccessChain %_ptr_Uniform_int %__0 %int_0 %25
+ %28 = OpLoad %int %27
+ %30 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0 %19
+ OpStore %30 %28
+ OpReturn
+ OpFunctionEnd
+[test]
+uniform ubo 0:0 int 0 0
+uniform ubo 0:0 int 16 1
+ssbo 0:1 subdata int 0 -1 -1
+
+compute entrypoint main
+compute 1 1 2
+
+probe ssbo int 0:1 0 == 0 1
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; #version 430
+;
+; layout(local_size_x = 2) in;
+; layout(local_size_y = 2) in;
+; layout(local_size_z = 2) in;
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; uint x[8];
+; };
+;
+; shared uint wg_data[8];
+;
+; void main() {
+; atomicExchange(wg_data[gl_LocalInvocationIndex], gl_LocalInvocationIndex);
+; uint val = atomicExchange(wg_data[(gl_LocalInvocationIndex+1)%8], 0);
+; x[gl_LocalInvocationIndex] = val;
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %wg_data %gl_LocalInvocationIndex %_
+ OpExecutionMode %main LocalSize 2 2 2
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %wg_data "wg_data"
+ OpName %gl_LocalInvocationIndex "gl_LocalInvocationIndex"
+ OpName %val "val"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "x"
+ OpName %_ ""
+ OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_8_0 ArrayStride 4
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_8 = OpConstant %uint 8
+%_arr_uint_uint_8 = OpTypeArray %uint %uint_8
+%_ptr_Workgroup__arr_uint_uint_8 = OpTypePointer Workgroup %_arr_uint_uint_8
+ %wg_data = OpVariable %_ptr_Workgroup__arr_uint_uint_8 Workgroup
+%_ptr_Input_uint = OpTypePointer Input %uint
+%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+%_arr_uint_uint_8_0 = OpTypeArray %uint %uint_8
+%output_buffer = OpTypeStruct %_arr_uint_uint_8_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+ %v3uint = OpTypeVector %uint 3
+ %uint_2 = OpConstant %uint 2
+%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_2 %uint_2 %uint_2
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %val = OpVariable %_ptr_Function_uint Function
+ %13 = OpLoad %uint %gl_LocalInvocationIndex
+ %15 = OpAccessChain %_ptr_Workgroup_uint %wg_data %13
+ %16 = OpLoad %uint %gl_LocalInvocationIndex
+ %19 = OpAtomicExchange %uint %15 %uint_1 %uint_0 %16
+ %22 = OpLoad %uint %gl_LocalInvocationIndex
+ %23 = OpIAdd %uint %22 %uint_1
+ %24 = OpUMod %uint %23 %uint_8
+ %25 = OpAccessChain %_ptr_Workgroup_uint %wg_data %24
+ %26 = OpAtomicExchange %uint %25 %uint_1 %uint_0 %uint_0
+ OpStore %val %26
+ %33 = OpLoad %uint %gl_LocalInvocationIndex
+ %34 = OpLoad %uint %val
+ %36 = OpAccessChain %_ptr_StorageBuffer_uint %_ %int_0 %33
+ OpStore %36 %34
+ OpReturn
+ OpFunctionEnd
+
+[test]
+ssbo 0:1 subdata int 0 -1 -1 -1 -1 -1 -1 -1 -1
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 1 2 3 4 5 6 7 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; A fragment shader with a push constant.
+;
+; #version 430
+;
+; layout(push_constant) uniform pushConstants {
+; vec4 in_val;
+; } u_pushConstants;
+;
+; layout(location = 0) out vec4 outColor;
+;
+; void main() {
+; outColor = u_pushConstants.in_val;
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %outColor %u_pushConstants
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %outColor "outColor"
+ OpName %pushConstants "pushConstants"
+ OpMemberName %pushConstants 0 "in_val"
+ OpName %u_pushConstants "u_pushConstants"
+ OpDecorate %outColor Location 0
+ OpMemberDecorate %pushConstants 0 Offset 0
+ OpDecorate %pushConstants Block
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %outColor = OpVariable %_ptr_Output_v4float Output
+%pushConstants = OpTypeStruct %v4float
+%_ptr_PushConstant_pushConstants = OpTypePointer PushConstant %pushConstants
+%u_pushConstants = OpVariable %_ptr_PushConstant_pushConstants PushConstant
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %16 = OpAccessChain %_ptr_PushConstant_v4float %u_pushConstants %int_0
+ %17 = OpLoad %v4float %16
+ OpStore %outColor %17
+ OpReturn
+ OpFunctionEnd
+[test]
+uniform float 0 0.2 0.3 0.4 0.1
+draw rect -1 -1 2 2
+
+probe rect rgba (0, 0, 250, 250) (0.2 0.3 0.4 0.1)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; A fragment shader with a ubo.
+;
+; #version 430
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; vec4 data_SSBO[];
+; };
+;
+; layout(location = 0) out vec4 outColor;
+;
+; void main() {
+; outColor = data_SSBO[0];
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %_ %outColor
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %outColor "outColor"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "data_SSBO"
+ OpName %_ ""
+ OpDecorate %outColor Location 0
+ OpDecorate %_runtimearr_v4float ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %outColor = OpVariable %_ptr_Output_v4float Output
+%_runtimearr_v4float = OpTypeRuntimeArray %v4float
+%input_buffer = OpTypeStruct %_runtimearr_v4float
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %17 = OpAccessChain %_ptr_StorageBuffer_v4float %_ %int_0 %int_0
+ %18 = OpLoad %v4float %17
+ OpStore %outColor %18
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:0 subdata float 0 0.2 0.3 0.4 0.1
+draw rect -1 -1 2 2
+
+probe rect rgba (0, 0, 250, 250) (0.2 0.3 0.4 0.1)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; A fragment shader with a ubo.
+;
+; #version 430
+;
+; layout(binding = 0) uniform input_buffer
+; {
+; vec4 in_data;
+; };
+;
+; layout(location = 0) out vec4 outColor;
+;
+; void main() {
+; outColor = in_data;
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %_ %outColor
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 430
+ OpName %main "main"
+ OpName %outColor "outColor"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_data"
+ OpName %_ ""
+ OpDecorate %outColor Location 0
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %outColor = OpVariable %_ptr_Output_v4float Output
+%input_buffer = OpTypeStruct %v4float
+%_ptr_Uniform_input_buffer = OpTypePointer Uniform %input_buffer
+ %_ = OpVariable %_ptr_Uniform_input_buffer Uniform
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %16 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0
+ %17 = OpLoad %v4float %16
+ OpStore %outColor %17
+ OpReturn
+ OpFunctionEnd
+[test]
+uniform ubo 0:0 float 0 0.2 0.3 0.4 0.1
+draw rect -1 -1 2 2
+
+probe rect rgba (0, 0, 250, 250) (0.2 0.3 0.4 0.1)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+geometryShader
+
+[vertex shader passthrough]
+[geometry shader spirv]
+; Test a geometry shader with a push constant in the OpEntryPoint.
+; #version 450
+;
+; layout(triangles) in;
+; layout(triangle_strip, max_vertices = 3) out;
+;
+; layout(push_constant) uniform pushConstants {
+; float factor;
+; } u_pushConstants;
+;
+; void main()
+; {
+; for( int i = 0; i < 3; i++ ) {
+; vec3 point = gl_in[i].gl_Position.xyz;
+; gl_Position = vec4(point * u_pushConstants.factor, 1.0);
+; EmitVertex();
+; }
+; EndPrimitive();
+; }
+
+ OpCapability Geometry
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Geometry %main "main" %gl_in %_ %u_pushConstants
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main Invocations 1
+ OpExecutionMode %main OutputTriangleStrip
+ OpExecutionMode %main OutputVertices 3
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %i "i"
+ OpName %point "point"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %pushConstants "pushConstants"
+ OpMemberName %pushConstants 0 "factor"
+ OpName %u_pushConstants "u_pushConstants"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpMemberDecorate %pushConstants 0 Offset 0
+ OpDecorate %pushConstants Block
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %int_3 = OpConstant %int 3
+ %bool = OpTypeBool
+ %float = OpTypeFloat 32
+ %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3
+%_ptr_Input__arr_gl_PerVertex_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_uint_3
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_3 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+ %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+%pushConstants = OpTypeStruct %float
+%_ptr_PushConstant_pushConstants = OpTypePointer PushConstant %pushConstants
+%u_pushConstants = OpVariable %_ptr_PushConstant_pushConstants PushConstant
+%_ptr_PushConstant_float = OpTypePointer PushConstant %float
+ %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %int_1 = OpConstant %int 1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ %point = OpVariable %_ptr_Function_v3float Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 None
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %18 = OpSLessThan %bool %15 %int_3
+ OpBranchConditional %18 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
+ %35 = OpLoad %v4float %34
+ %36 = OpVectorShuffle %v3float %35 %35 0 1 2
+ OpStore %point %36
+ %40 = OpLoad %v3float %point
+ %45 = OpAccessChain %_ptr_PushConstant_float %u_pushConstants %int_0
+ %46 = OpLoad %float %45
+ %47 = OpVectorTimesScalar %v3float %40 %46
+ %49 = OpCompositeExtract %float %47 0
+ %50 = OpCompositeExtract %float %47 1
+ %51 = OpCompositeExtract %float %47 2
+ %52 = OpCompositeConstruct %v4float %49 %50 %51 %float_1
+ %54 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %54 %52
+ OpEmitVertex
+ OpBranch %13
+ %13 = OpLabel
+ %55 = OpLoad %int %i
+ %57 = OpIAdd %int %55 %int_1
+ OpStore %i %57
+ OpBranch %10
+ %12 = OpLabel
+ OpEndPrimitive
+ OpReturn
+ OpFunctionEnd
+[fragment shader]
+#version 430
+layout(location = 0) out vec4 outColor;
+void main() {
+ outColor = vec4(0.5, 0.5, 0.5, 0.5);
+}
+
+[test]
+uniform float 0 0.5
+clear
+draw rect -1 -1 2 2
+
+probe rect rgba (62, 62, 125, 125) (0.5 0.5 0.5 0.5)
+probe rect rgba (0, 0, 250, 62) (0.0 0.0 0.0 0.0)
+probe rect rgba (0, 0, 62, 250) (0.0 0.0 0.0 0.0)
+probe rect rgba (187, 0, 63, 250) (0.0 0.0 0.0 0.0)
+probe rect rgba (0, 187, 250, 63) (0.0 0.0 0.0 0.0)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+geometryShader
+
+[vertex shader passthrough]
+[geometry shader spirv]
+; Test a geometry shader with an SSBO on the OpEntryPoint instruction.
+; #version 450
+;
+; layout(triangles) in;
+; layout(triangle_strip, max_vertices = 3) out;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; float factor;
+; };
+;
+; void main()
+; {
+; for( int i = 0; i < 3; i++ ) {
+; vec3 point = gl_in[i].gl_Position.xyz;
+; gl_Position = vec4(point * factor, 1.0);
+; EmitVertex();
+; }
+; EndPrimitive();
+; }
+ OpCapability Geometry
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Geometry %main "main" %gl_in %_ %__0
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main Invocations 1
+ OpExecutionMode %main OutputTriangleStrip
+ OpExecutionMode %main OutputVertices 3
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %i "i"
+ OpName %point "point"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "factor"
+ OpName %__0 ""
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %int_3 = OpConstant %int 3
+ %bool = OpTypeBool
+ %float = OpTypeFloat 32
+ %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3
+%_ptr_Input__arr_gl_PerVertex_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_uint_3
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_3 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+ %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+%input_buffer = OpTypeStruct %float
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+ %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %int_1 = OpConstant %int 1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ %point = OpVariable %_ptr_Function_v3float Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 None
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %18 = OpSLessThan %bool %15 %int_3
+ OpBranchConditional %18 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
+ %35 = OpLoad %v4float %34
+ %36 = OpVectorShuffle %v3float %35 %35 0 1 2
+ OpStore %point %36
+ %40 = OpLoad %v3float %point
+ %45 = OpAccessChain %_ptr_StorageBuffer_float %__0 %int_0
+ %46 = OpLoad %float %45
+ %47 = OpVectorTimesScalar %v3float %40 %46
+ %49 = OpCompositeExtract %float %47 0
+ %50 = OpCompositeExtract %float %47 1
+ %51 = OpCompositeExtract %float %47 2
+ %52 = OpCompositeConstruct %v4float %49 %50 %51 %float_1
+ %54 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %54 %52
+ OpEmitVertex
+ OpBranch %13
+ %13 = OpLabel
+ %55 = OpLoad %int %i
+ %57 = OpIAdd %int %55 %int_1
+ OpStore %i %57
+ OpBranch %10
+ %12 = OpLabel
+ OpEndPrimitive
+ OpReturn
+ OpFunctionEnd
+[fragment shader]
+#version 430
+layout(location = 0) out vec4 outColor;
+void main() {
+ outColor = vec4(0.5, 0.5, 0.5, 0.5);
+}
+
+[test]
+ssbo 0:0 subdata float 0 0.5
+clear
+draw rect -1 -1 2 2
+
+probe rect rgba (62, 62, 125, 125) (0.5 0.5 0.5 0.5)
+probe rect rgba (0, 0, 250, 62) (0.0 0.0 0.0 0.0)
+probe rect rgba (0, 0, 62, 250) (0.0 0.0 0.0 0.0)
+probe rect rgba (187, 0, 63, 250) (0.0 0.0 0.0 0.0)
+probe rect rgba (0, 187, 250, 63) (0.0 0.0 0.0 0.0)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+geometryShader
+
+[vertex shader passthrough]
+[geometry shader spirv]
+; Test a geometry shader with a UBO on the OpEntryPoint instruction.
+; #version 450
+;
+; layout(triangles) in;
+; layout(triangle_strip, max_vertices = 3) out;
+;
+; layout(binding = 0) uniform input_buffer
+; {
+; float factor;
+; };
+;
+; void main()
+; {
+; for( int i = 0; i < 3; i++ ) {
+; vec3 point = gl_in[i].gl_Position.xyz;
+; gl_Position = vec4(point * factor, 1.0);
+; EmitVertex();
+; }
+; EndPrimitive();
+; }
+
+ OpCapability Geometry
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Geometry %main "main" %gl_in %_ %__0
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main Invocations 1
+ OpExecutionMode %main OutputTriangleStrip
+ OpExecutionMode %main OutputVertices 3
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %i "i"
+ OpName %point "point"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "factor"
+ OpName %__0 ""
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %int_3 = OpConstant %int 3
+ %bool = OpTypeBool
+ %float = OpTypeFloat 32
+ %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3
+%_ptr_Input__arr_gl_PerVertex_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_uint_3
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_3 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+ %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+%input_buffer = OpTypeStruct %float
+%_ptr_Uniform_input_buffer = OpTypePointer Uniform %input_buffer
+ %__0 = OpVariable %_ptr_Uniform_input_buffer Uniform
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+ %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %int_1 = OpConstant %int 1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ %point = OpVariable %_ptr_Function_v3float Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 None
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %18 = OpSLessThan %bool %15 %int_3
+ OpBranchConditional %18 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
+ %35 = OpLoad %v4float %34
+ %36 = OpVectorShuffle %v3float %35 %35 0 1 2
+ OpStore %point %36
+ %40 = OpLoad %v3float %point
+ %45 = OpAccessChain %_ptr_Uniform_float %__0 %int_0
+ %46 = OpLoad %float %45
+ %47 = OpVectorTimesScalar %v3float %40 %46
+ %49 = OpCompositeExtract %float %47 0
+ %50 = OpCompositeExtract %float %47 1
+ %51 = OpCompositeExtract %float %47 2
+ %52 = OpCompositeConstruct %v4float %49 %50 %51 %float_1
+ %54 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %54 %52
+ OpEmitVertex
+ OpBranch %13
+ %13 = OpLabel
+ %55 = OpLoad %int %i
+ %57 = OpIAdd %int %55 %int_1
+ OpStore %i %57
+ OpBranch %10
+ %12 = OpLabel
+ OpEndPrimitive
+ OpReturn
+ OpFunctionEnd
+[fragment shader]
+#version 430
+layout(location = 0) out vec4 outColor;
+void main() {
+ outColor = vec4(0.5, 0.5, 0.5, 0.5);
+}
+
+[test]
+uniform ubo 0:0 float 0 0.5
+clear
+draw rect -1 -1 2 2
+
+probe rect rgba (62, 62, 125, 125) (0.5 0.5 0.5 0.5)
+probe rect rgba (0, 0, 250, 62) (0.0 0.0 0.0 0.0)
+probe rect rgba (0, 0, 62, 250) (0.0 0.0 0.0 0.0)
+probe rect rgba (187, 0, 63, 250) (0.0 0.0 0.0 0.0)
+probe rect rgba (0, 187, 250, 63) (0.0 0.0 0.0 0.0)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+tessellationShader
+
+[vertex shader]
+#version 450
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color;
+layout(location = 0) out vec4 tsc_color;
+
+void main() {
+ gl_Position = position;
+ tsc_color = vert_color;
+}
+
+[tessellation control shader spirv]
+; Test tessellation control shader with push constant on entry point.
+; But also modified to set gl_TessLevelInner gl_TessLevelOuter
+; #version 450
+; #extension GL_ARB_separate_shader_objects : enable
+;
+; layout(vertices = 3) out;
+;
+; layout(location = 0) in vec4 tsc_color[];
+; layout(location = 0) out vec4 tse_color[];
+;
+; layout(push_constant) uniform pushConstants {
+; vec4 in_val;
+; } pc;
+; #define ID gl_InvocationID
+;
+; void main()
+; {
+; gl_out[ID].gl_Position = gl_in[ID].gl_Position;
+; tse_color[ID] = tsc_color[ID]+pc.in_val;
+; }
+ OpCapability Tessellation
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationControl %main "main" %gl_out %gl_InvocationID %gl_in %tse_color %pc %tsc_color %gl_TessLevelInner %gl_TessLevelOuter
+ OpExecutionMode %main OutputVertices 3
+ OpSource GLSL 450
+ OpSourceExtension "GL_ARB_separate_shader_objects"
+ OpName %main "main"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_out "gl_out"
+ OpName %gl_InvocationID "gl_InvocationID"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %tse_color "tse_color"
+ OpName %pushConstants "pushConstants"
+ OpMemberName %pushConstants 0 "in_val"
+ OpName %pc "pc"
+ OpName %tsc_color "tsc_color"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %gl_InvocationID BuiltIn InvocationId
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpDecorate %tse_color Location 0
+ OpMemberDecorate %pushConstants 0 Offset 0
+ OpDecorate %pushConstants Block
+ OpDecorate %tsc_color Location 0
+ OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
+ OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
+ OpDecorate %gl_TessLevelInner Patch
+ OpDecorate %gl_TessLevelOuter Patch
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_4 = OpConstant %uint 4
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+ %float_1 = OpConstant %float 1.0
+ %arr_2_1 = OpConstantComposite %_arr_float_uint_2 %float_1 %float_1
+ %arr_4_1 = OpConstantComposite %_arr_float_uint_4 %float_1 %float_1 %float_1 %float_1
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+%gl_TessLevelInner = OpVariable %_ptr_Output__arr_float_uint_2 Output %arr_2_1
+%gl_TessLevelOuter = OpVariable %_ptr_Output__arr_float_uint_4 Output %arr_4_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3
+%_ptr_Output__arr_gl_PerVertex_uint_3 = OpTypePointer Output %_arr_gl_PerVertex_uint_3
+ %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_3 Output
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+ %int_0 = OpConstant %int 0
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_0_uint_32 = OpTypeArray %gl_PerVertex_0 %uint_32
+%_ptr_Input__arr_gl_PerVertex_0_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_32
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_32 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+%_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3
+ %tse_color = OpVariable %_ptr_Output__arr_v4float_uint_3 Output
+%pushConstants = OpTypeStruct %v4float
+%_ptr_PushConstant_pushConstants = OpTypePointer PushConstant %pushConstants
+ %pc = OpVariable %_ptr_PushConstant_pushConstants PushConstant
+%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float
+%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
+%_ptr_Input__arr_v4float_uint_32 = OpTypePointer Input %_arr_v4float_uint_32
+ %tsc_color = OpVariable %_ptr_Input__arr_v4float_uint_32 Input
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %19 = OpLoad %int %gl_InvocationID
+ %26 = OpLoad %int %gl_InvocationID
+ %28 = OpAccessChain %_ptr_Input_v4float %gl_in %26 %int_0
+ %29 = OpLoad %v4float %28
+ %31 = OpAccessChain %_ptr_Output_v4float %gl_out %19 %int_0
+ OpStore %31 %29
+ %35 = OpLoad %int %gl_InvocationID
+ %36 = OpLoad %int %gl_InvocationID
+ %37 = OpAccessChain %_ptr_Input_v4float %tsc_color %36
+ %38 = OpLoad %v4float %37
+ %43 = OpAccessChain %_ptr_PushConstant_v4float %pc %int_0
+ %44 = OpLoad %v4float %43
+ %45 = OpFAdd %v4float %38 %44
+ %46 = OpAccessChain %_ptr_Output_v4float %tse_color %35
+ OpStore %46 %45
+ OpReturn
+ OpFunctionEnd
+[tessellation evaluation shader]
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(triangles, equal_spacing, cw) in;
+
+layout(location = 0) in vec4 tse_color[];
+layout(location = 0) out vec4 frag_color;
+
+void main()
+{
+ vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+ vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+ vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+ gl_Position = p0 + p1 + p2;
+ frag_color = tse_color[0];
+}
+
+[fragment shader]
+#version 450
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main() {
+ final_color = frag_color;
+}
+
+[vertex data]
+# position vert_color
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+
+# Red for entire frame
+# R8 G8 R8 G8 B8
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ 127 -128 255 0 0
+
+[test]
+uniform float 0 0.0 0.0 0.3 0.0
+clear
+draw arrays PATCH_LIST 0 6
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0, 0.3)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+tessellationShader
+
+[vertex shader]
+#version 450
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color;
+layout(location = 0) out vec4 tsc_color;
+
+void main() {
+ gl_Position = position;
+ tsc_color = vert_color;
+}
+
+[tessellation control shader spirv]
+; Test tessellation control shader with an ssbo on the entry point.
+; #version 450
+; #extension GL_ARB_separate_shader_objects : enable
+;
+; layout(vertices = 3) out;
+;
+; layout(location = 0) in vec4 tsc_color[];
+; layout(location = 0) out vec4 tse_color[];
+;
+; #define ID gl_InvocationID
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; vec4 in_val;
+; };
+;
+; void main()
+; {
+; gl_out[ID].gl_Position = gl_in[ID].gl_Position;
+; tse_color[ID] = tsc_color[ID]+in_val;
+; }
+ OpCapability Tessellation
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationControl %main "main" %gl_out %gl_InvocationID %gl_in %tse_color %_ %tsc_color %gl_TessLevelInner %gl_TessLevelOuter
+ OpExecutionMode %main OutputVertices 3
+ OpSource GLSL 450
+ OpSourceExtension "GL_ARB_separate_shader_objects"
+ OpName %main "main"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_out "gl_out"
+ OpName %gl_InvocationID "gl_InvocationID"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %tse_color "tse_color"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_val"
+ OpName %_ ""
+ OpName %tsc_color "tsc_color"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %gl_InvocationID BuiltIn InvocationId
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpDecorate %tse_color Location 0
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %tsc_color Location 0
+ OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
+ OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
+ OpDecorate %gl_TessLevelInner Patch
+ OpDecorate %gl_TessLevelOuter Patch
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_4 = OpConstant %uint 4
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+ %float_1 = OpConstant %float 1.0
+ %arr_2_1 = OpConstantComposite %_arr_float_uint_2 %float_1 %float_1
+ %arr_4_1 = OpConstantComposite %_arr_float_uint_4 %float_1 %float_1 %float_1 %float_1
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+%gl_TessLevelInner = OpVariable %_ptr_Output__arr_float_uint_2 Output %arr_2_1
+%gl_TessLevelOuter = OpVariable %_ptr_Output__arr_float_uint_4 Output %arr_4_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3
+%_ptr_Output__arr_gl_PerVertex_uint_3 = OpTypePointer Output %_arr_gl_PerVertex_uint_3
+ %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_3 Output
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+ %int_0 = OpConstant %int 0
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_0_uint_32 = OpTypeArray %gl_PerVertex_0 %uint_32
+%_ptr_Input__arr_gl_PerVertex_0_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_32
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_32 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+%_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3
+ %tse_color = OpVariable %_ptr_Output__arr_v4float_uint_3 Output
+%input_buffer = OpTypeStruct %v4float
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
+%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
+%_ptr_Input__arr_v4float_uint_32 = OpTypePointer Input %_arr_v4float_uint_32
+ %tsc_color = OpVariable %_ptr_Input__arr_v4float_uint_32 Input
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %19 = OpLoad %int %gl_InvocationID
+ %26 = OpLoad %int %gl_InvocationID
+ %28 = OpAccessChain %_ptr_Input_v4float %gl_in %26 %int_0
+ %29 = OpLoad %v4float %28
+ %31 = OpAccessChain %_ptr_Output_v4float %gl_out %19 %int_0
+ OpStore %31 %29
+ %35 = OpLoad %int %gl_InvocationID
+ %36 = OpLoad %int %gl_InvocationID
+ %37 = OpAccessChain %_ptr_Input_v4float %tsc_color %36
+ %38 = OpLoad %v4float %37
+ %43 = OpAccessChain %_ptr_StorageBuffer_v4float %_ %int_0
+ %44 = OpLoad %v4float %43
+ %45 = OpFAdd %v4float %38 %44
+ %46 = OpAccessChain %_ptr_Output_v4float %tse_color %35
+ OpStore %46 %45
+ OpReturn
+ OpFunctionEnd
+
+[tessellation evaluation shader]
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(triangles, equal_spacing, cw) in;
+
+layout(location = 0) in vec4 tse_color[];
+layout(location = 0) out vec4 frag_color;
+
+void main()
+{
+ vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+ vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+ vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+ gl_Position = p0 + p1 + p2;
+ frag_color = tse_color[0];
+}
+
+[fragment shader]
+#version 450
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main() {
+ final_color = frag_color;
+}
+
+[vertex data]
+# position vert_color
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+
+# Red for entire frame
+# R8 G8 R8 G8 B8
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ 127 -128 255 0 0
+
+[test]
+ssbo 0:0 subdata float 0 0.0 0.0 0.3 0.0
+clear
+draw arrays PATCH_LIST 0 6
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0, 0.3)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+tessellationShader
+
+[vertex shader]
+#version 450
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color;
+layout(location = 0) out vec4 tsc_color;
+
+void main() {
+ gl_Position = position;
+ tsc_color = vert_color;
+}
+
+[tessellation control shader spirv]
+; Test tessellation control shader with a ubo on the entry point.
+; #version 450
+; #extension GL_ARB_separate_shader_objects : enable
+;
+; layout(vertices = 3) out;
+;
+; layout(location = 0) in vec4 tsc_color[];
+; layout(location = 0) out vec4 tse_color[];
+;
+; #define ID gl_InvocationID
+;
+; layout(binding = 0) uniform input_buffer
+; {
+; vec4 in_val;
+; };
+;
+; void main()
+; {
+; gl_out[ID].gl_Position = gl_in[ID].gl_Position;
+; tse_color[ID] = tsc_color[ID]+in_val;
+; }
+ OpCapability Tessellation
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationControl %main "main" %gl_out %gl_InvocationID %gl_in %tse_color %_ %tsc_color %gl_TessLevelInner %gl_TessLevelOuter
+ OpExecutionMode %main OutputVertices 3
+ OpSource GLSL 450
+ OpSourceExtension "GL_ARB_separate_shader_objects"
+ OpName %main "main"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_out "gl_out"
+ OpName %gl_InvocationID "gl_InvocationID"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %tse_color "tse_color"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_val"
+ OpName %_ ""
+ OpName %tsc_color "tsc_color"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %gl_InvocationID BuiltIn InvocationId
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpDecorate %tse_color Location 0
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %tsc_color Location 0
+ OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
+ OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
+ OpDecorate %gl_TessLevelInner Patch
+ OpDecorate %gl_TessLevelOuter Patch
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_4 = OpConstant %uint 4
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3
+%_ptr_Output__arr_gl_PerVertex_uint_3 = OpTypePointer Output %_arr_gl_PerVertex_uint_3
+ %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_3 Output
+ %int = OpTypeInt 32 1
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+ %float_1 = OpConstant %float 1.0
+ %arr_2_1 = OpConstantComposite %_arr_float_uint_2 %float_1 %float_1
+ %arr_4_1 = OpConstantComposite %_arr_float_uint_4 %float_1 %float_1 %float_1 %float_1
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+%gl_TessLevelInner = OpVariable %_ptr_Output__arr_float_uint_2 Output %arr_2_1
+%gl_TessLevelOuter = OpVariable %_ptr_Output__arr_float_uint_4 Output %arr_4_1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+ %int_0 = OpConstant %int 0
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_0_uint_32 = OpTypeArray %gl_PerVertex_0 %uint_32
+%_ptr_Input__arr_gl_PerVertex_0_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_32
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_32 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+%_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3
+ %tse_color = OpVariable %_ptr_Output__arr_v4float_uint_3 Output
+%input_buffer = OpTypeStruct %v4float
+%_ptr_Uniform_input_buffer = OpTypePointer Uniform %input_buffer
+ %_ = OpVariable %_ptr_Uniform_input_buffer Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
+%_ptr_Input__arr_v4float_uint_32 = OpTypePointer Input %_arr_v4float_uint_32
+ %tsc_color = OpVariable %_ptr_Input__arr_v4float_uint_32 Input
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %19 = OpLoad %int %gl_InvocationID
+ %26 = OpLoad %int %gl_InvocationID
+ %28 = OpAccessChain %_ptr_Input_v4float %gl_in %26 %int_0
+ %29 = OpLoad %v4float %28
+ %31 = OpAccessChain %_ptr_Output_v4float %gl_out %19 %int_0
+ OpStore %31 %29
+ %35 = OpLoad %int %gl_InvocationID
+ %36 = OpLoad %int %gl_InvocationID
+ %37 = OpAccessChain %_ptr_Input_v4float %tsc_color %36
+ %38 = OpLoad %v4float %37
+ %43 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0
+ %44 = OpLoad %v4float %43
+ %45 = OpFAdd %v4float %38 %44
+ %46 = OpAccessChain %_ptr_Output_v4float %tse_color %35
+ OpStore %46 %45
+ OpReturn
+ OpFunctionEnd
+[tessellation evaluation shader]
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(triangles, equal_spacing, cw) in;
+
+layout(location = 0) in vec4 tse_color[];
+layout(location = 0) out vec4 frag_color;
+
+void main()
+{
+ vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+ vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+ vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+ gl_Position = p0 + p1 + p2;
+ frag_color = tse_color[0];
+}
+
+[fragment shader]
+#version 450
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main() {
+ final_color = frag_color;
+}
+
+[vertex data]
+# position vert_color
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+
+# Red for entire frame
+# R8 G8 R8 G8 B8
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ 127 -128 255 0 0
+
+[test]
+uniform ubo 0:0 float 0 0.0 0.0 0.3 0.0
+clear
+draw arrays PATCH_LIST 0 6
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0, 0.3)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+tessellationShader
+
+[vertex shader]
+#version 450
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color;
+layout(location = 0) out vec4 tsc_color;
+
+void main() {
+ gl_Position = position;
+ tsc_color = vert_color;
+}
+
+[tessellation control shader]
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(vertices = 3) out;
+
+layout(location = 0) in vec4 tsc_color[];
+layout(location = 0) out vec4 tse_color[];
+
+#define ID gl_InvocationID
+
+void main()
+{
+ gl_out[ID].gl_Position = gl_in[ID].gl_Position;
+ tse_color[ID] = tsc_color[ID];
+ gl_TessLevelOuter[0] = 1.0;
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = 1.0;
+ gl_TessLevelInner[0] = 1.0;
+ gl_TessLevelInner[1] = 1.0;
+}
+
+[tessellation evaluation shader spirv]
+; Test tessellation evaluation shader with a push constant on the entry point.
+; #version 450
+; #extension GL_ARB_separate_shader_objects : enable
+;
+; layout(triangles, equal_spacing, cw) in;
+;
+; layout(location = 0) in vec4 tse_color[];
+; layout(location = 0) out vec4 frag_color;
+;
+; layout(push_constant) uniform pushConstants {
+; vec4 in_val;
+; } pc;
+;
+; void main()
+; {
+; vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+; vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+; vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+; gl_Position = p0 + p1 + p2;
+; frag_color = tse_color[0]+pc.in_val;
+; }
+ OpCapability Tessellation
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationEvaluation %main "main" %gl_TessCoord %gl_in %_ %frag_color %tse_color %pc
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main SpacingEqual
+ OpExecutionMode %main VertexOrderCw
+ OpSource GLSL 450
+ OpSourceExtension "GL_ARB_separate_shader_objects"
+ OpName %main "main"
+ OpName %p0 "p0"
+ OpName %gl_TessCoord "gl_TessCoord"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %p1 "p1"
+ OpName %p2 "p2"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %frag_color "frag_color"
+ OpName %tse_color "tse_color"
+ OpName %pushConstants "pushConstants"
+ OpMemberName %pushConstants 0 "in_val"
+ OpName %pc "pc"
+ OpDecorate %gl_TessCoord BuiltIn TessCoord
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpDecorate %frag_color Location 0
+ OpDecorate %tse_color Location 0
+ OpMemberDecorate %pushConstants 0 Offset 0
+ OpDecorate %pushConstants Block
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%gl_TessCoord = OpVariable %_ptr_Input_v3float Input
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
+%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %int_2 = OpConstant %int 2
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+ %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %frag_color = OpVariable %_ptr_Output_v4float Output
+%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
+%_ptr_Input__arr_v4float_uint_32 = OpTypePointer Input %_arr_v4float_uint_32
+ %tse_color = OpVariable %_ptr_Input__arr_v4float_uint_32 Input
+%pushConstants = OpTypeStruct %v4float
+%_ptr_PushConstant_pushConstants = OpTypePointer PushConstant %pushConstants
+ %pc = OpVariable %_ptr_PushConstant_pushConstants PushConstant
+%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %p0 = OpVariable %_ptr_Function_v4float Function
+ %p1 = OpVariable %_ptr_Function_v4float Function
+ %p2 = OpVariable %_ptr_Function_v4float Function
+ %16 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_0
+ %17 = OpLoad %float %16
+ %28 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0
+ %29 = OpLoad %v4float %28
+ %30 = OpVectorTimesScalar %v4float %29 %17
+ OpStore %p0 %30
+ %32 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_1
+ %33 = OpLoad %float %32
+ %35 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
+ %36 = OpLoad %v4float %35
+ %37 = OpVectorTimesScalar %v4float %36 %33
+ OpStore %p1 %37
+ %40 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_2
+ %41 = OpLoad %float %40
+ %43 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0
+ %44 = OpLoad %v4float %43
+ %45 = OpVectorTimesScalar %v4float %44 %41
+ OpStore %p2 %45
+ %49 = OpLoad %v4float %p0
+ %50 = OpLoad %v4float %p1
+ %51 = OpFAdd %v4float %49 %50
+ %52 = OpLoad %v4float %p2
+ %53 = OpFAdd %v4float %51 %52
+ %55 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %55 %53
+ %60 = OpAccessChain %_ptr_Input_v4float %tse_color %int_0
+ %61 = OpLoad %v4float %60
+ %66 = OpAccessChain %_ptr_PushConstant_v4float %pc %int_0
+ %67 = OpLoad %v4float %66
+ %68 = OpFAdd %v4float %61 %67
+ OpStore %frag_color %68
+ OpReturn
+ OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main() {
+ final_color = frag_color;
+}
+
+[vertex data]
+# position vert_color
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+
+# Red for entire frame
+# R8 G8 R8 G8 B8
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ 127 -128 255 0 0
+
+[test]
+uniform float 0 0.0 0.0 0.3 0.0
+clear
+draw arrays PATCH_LIST 0 6
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0, 0.3)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+tessellationShader
+
+[vertex shader]
+#version 450
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color;
+layout(location = 0) out vec4 tsc_color;
+
+void main() {
+ gl_Position = position;
+ tsc_color = vert_color;
+}
+
+[tessellation control shader]
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(vertices = 3) out;
+
+layout(location = 0) in vec4 tsc_color[];
+layout(location = 0) out vec4 tse_color[];
+
+#define ID gl_InvocationID
+
+void main()
+{
+ gl_out[ID].gl_Position = gl_in[ID].gl_Position;
+ tse_color[ID] = tsc_color[ID];
+ gl_TessLevelOuter[0] = 1.0;
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = 1.0;
+ gl_TessLevelInner[0] = 1.0;
+ gl_TessLevelInner[1] = 1.0;
+}
+
+[tessellation evaluation shader spirv]
+; Test tessellation evaluation shader with an SSBO on the entry point.
+; #version 450
+; #extension GL_ARB_separate_shader_objects : enable
+;
+; layout(triangles, equal_spacing, cw) in;
+;
+; layout(location = 0) in vec4 tse_color[];
+; layout(location = 0) out vec4 frag_color;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; vec4 in_val;
+; };
+;
+; void main()
+; {
+; vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+; vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+; vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+; gl_Position = p0 + p1 + p2;
+; frag_color = tse_color[0]+in_val;
+; }
+ OpCapability Tessellation
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationEvaluation %main "main" %gl_TessCoord %gl_in %_ %frag_color %tse_color %__0
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main SpacingEqual
+ OpExecutionMode %main VertexOrderCw
+ OpSource GLSL 450
+ OpSourceExtension "GL_ARB_separate_shader_objects"
+ OpName %main "main"
+ OpName %p0 "p0"
+ OpName %gl_TessCoord "gl_TessCoord"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %p1 "p1"
+ OpName %p2 "p2"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %frag_color "frag_color"
+ OpName %tse_color "tse_color"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_val"
+ OpName %__0 ""
+ OpDecorate %gl_TessCoord BuiltIn TessCoord
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpDecorate %frag_color Location 0
+ OpDecorate %tse_color Location 0
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%gl_TessCoord = OpVariable %_ptr_Input_v3float Input
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
+%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %int_2 = OpConstant %int 2
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+ %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %frag_color = OpVariable %_ptr_Output_v4float Output
+%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
+%_ptr_Input__arr_v4float_uint_32 = OpTypePointer Input %_arr_v4float_uint_32
+ %tse_color = OpVariable %_ptr_Input__arr_v4float_uint_32 Input
+%input_buffer = OpTypeStruct %v4float
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %p0 = OpVariable %_ptr_Function_v4float Function
+ %p1 = OpVariable %_ptr_Function_v4float Function
+ %p2 = OpVariable %_ptr_Function_v4float Function
+ %16 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_0
+ %17 = OpLoad %float %16
+ %28 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0
+ %29 = OpLoad %v4float %28
+ %30 = OpVectorTimesScalar %v4float %29 %17
+ OpStore %p0 %30
+ %32 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_1
+ %33 = OpLoad %float %32
+ %35 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
+ %36 = OpLoad %v4float %35
+ %37 = OpVectorTimesScalar %v4float %36 %33
+ OpStore %p1 %37
+ %40 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_2
+ %41 = OpLoad %float %40
+ %43 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0
+ %44 = OpLoad %v4float %43
+ %45 = OpVectorTimesScalar %v4float %44 %41
+ OpStore %p2 %45
+ %49 = OpLoad %v4float %p0
+ %50 = OpLoad %v4float %p1
+ %51 = OpFAdd %v4float %49 %50
+ %52 = OpLoad %v4float %p2
+ %53 = OpFAdd %v4float %51 %52
+ %55 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %55 %53
+ %60 = OpAccessChain %_ptr_Input_v4float %tse_color %int_0
+ %61 = OpLoad %v4float %60
+ %66 = OpAccessChain %_ptr_StorageBuffer_v4float %__0 %int_0
+ %67 = OpLoad %v4float %66
+ %68 = OpFAdd %v4float %61 %67
+ OpStore %frag_color %68
+ OpReturn
+ OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main() {
+ final_color = frag_color;
+}
+
+[vertex data]
+# position vert_color
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+
+# Red for entire frame
+# R8 G8 R8 G8 B8
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ 127 -128 255 0 0
+
+[test]
+ssbo 0:0 subdata float 0 0.0 0.0 0.3 0.0
+clear
+draw arrays PATCH_LIST 0 6
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0, 0.3)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+tessellationShader
+
+[vertex shader]
+#version 450
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color;
+layout(location = 0) out vec4 tsc_color;
+
+void main() {
+ gl_Position = position;
+ tsc_color = vert_color;
+}
+
+[tessellation control shader]
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(vertices = 3) out;
+
+layout(location = 0) in vec4 tsc_color[];
+layout(location = 0) out vec4 tse_color[];
+
+#define ID gl_InvocationID
+
+void main()
+{
+ gl_out[ID].gl_Position = gl_in[ID].gl_Position;
+ tse_color[ID] = tsc_color[ID];
+ gl_TessLevelOuter[0] = 1.0;
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = 1.0;
+ gl_TessLevelInner[0] = 1.0;
+ gl_TessLevelInner[1] = 1.0;
+}
+
+[tessellation evaluation shader spirv]
+; Test tessellation evaluation shader with a UBO on the entry point.
+; #version 450
+; #extension GL_ARB_separate_shader_objects : enable
+;
+; layout(triangles, equal_spacing, cw) in;
+;
+; layout(location = 0) in vec4 tse_color[];
+; layout(location = 0) out vec4 frag_color;
+;
+; layout(binding = 0) uniform input_buffer
+; {
+; vec4 in_val;
+; };
+;
+; void main()
+; {
+; vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+; vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+; vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+; gl_Position = p0 + p1 + p2;
+; frag_color = tse_color[0]+in_val;
+; }
+ OpCapability Tessellation
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationEvaluation %main "main" %gl_TessCoord %gl_in %_ %frag_color %tse_color %__0
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main SpacingEqual
+ OpExecutionMode %main VertexOrderCw
+ OpSource GLSL 450
+ OpSourceExtension "GL_ARB_separate_shader_objects"
+ OpName %main "main"
+ OpName %p0 "p0"
+ OpName %gl_TessCoord "gl_TessCoord"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %gl_in "gl_in"
+ OpName %p1 "p1"
+ OpName %p2 "p2"
+ OpName %gl_PerVertex_0 "gl_PerVertex"
+ OpMemberName %gl_PerVertex_0 0 "gl_Position"
+ OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %frag_color "frag_color"
+ OpName %tse_color "tse_color"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_val"
+ OpName %__0 ""
+ OpDecorate %gl_TessCoord BuiltIn TessCoord
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex_0 Block
+ OpDecorate %frag_color Location 0
+ OpDecorate %tse_color Location 0
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%gl_TessCoord = OpVariable %_ptr_Input_v3float Input
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+ %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
+%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
+ %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %int_2 = OpConstant %int 2
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+ %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %frag_color = OpVariable %_ptr_Output_v4float Output
+%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
+%_ptr_Input__arr_v4float_uint_32 = OpTypePointer Input %_arr_v4float_uint_32
+ %tse_color = OpVariable %_ptr_Input__arr_v4float_uint_32 Input
+%input_buffer = OpTypeStruct %v4float
+%_ptr_Uniform_input_buffer = OpTypePointer Uniform %input_buffer
+ %__0 = OpVariable %_ptr_Uniform_input_buffer Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %p0 = OpVariable %_ptr_Function_v4float Function
+ %p1 = OpVariable %_ptr_Function_v4float Function
+ %p2 = OpVariable %_ptr_Function_v4float Function
+ %16 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_0
+ %17 = OpLoad %float %16
+ %28 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0
+ %29 = OpLoad %v4float %28
+ %30 = OpVectorTimesScalar %v4float %29 %17
+ OpStore %p0 %30
+ %32 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_1
+ %33 = OpLoad %float %32
+ %35 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
+ %36 = OpLoad %v4float %35
+ %37 = OpVectorTimesScalar %v4float %36 %33
+ OpStore %p1 %37
+ %40 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_2
+ %41 = OpLoad %float %40
+ %43 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0
+ %44 = OpLoad %v4float %43
+ %45 = OpVectorTimesScalar %v4float %44 %41
+ OpStore %p2 %45
+ %49 = OpLoad %v4float %p0
+ %50 = OpLoad %v4float %p1
+ %51 = OpFAdd %v4float %49 %50
+ %52 = OpLoad %v4float %p2
+ %53 = OpFAdd %v4float %51 %52
+ %55 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %55 %53
+ %60 = OpAccessChain %_ptr_Input_v4float %tse_color %int_0
+ %61 = OpLoad %v4float %60
+ %66 = OpAccessChain %_ptr_Uniform_v4float %__0 %int_0
+ %67 = OpLoad %v4float %66
+ %68 = OpFAdd %v4float %61 %67
+ OpStore %frag_color %68
+ OpReturn
+ OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main() {
+ final_color = frag_color;
+}
+
+[vertex data]
+# position vert_color
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+
+# Red for entire frame
+# R8 G8 R8 G8 B8
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ 127 -128 255 0 0
+
+[test]
+uniform ubo 0:0 float 0 0.0 0.0 0.3 0.0
+clear
+draw arrays PATCH_LIST 0 6
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0, 0.3)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader spirv]
+; Test a vertex shader with a push constant on the OpEntryPoint.
+;
+; #version 450
+;
+; layout(push_constant) uniform pushConstants {
+; vec2 in_val[4];
+; } u_pushConstants;
+;
+; void main() {
+; gl_Position = vec4(u_pushConstants.in_val[gl_VertexIndex], 0.0, 1.0);
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %_ %u_pushConstants %gl_VertexIndex
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %pushConstants "pushConstants"
+ OpMemberName %pushConstants 0 "in_val"
+ OpName %u_pushConstants "u_pushConstants"
+ OpName %gl_VertexIndex "gl_VertexIndex"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %_arr_v2float_uint_4 ArrayStride 8
+ OpMemberDecorate %pushConstants 0 Offset 0
+ OpDecorate %pushConstants Block
+ OpDecorate %gl_VertexIndex BuiltIn VertexIndex
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+ %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %v2float = OpTypeVector %float 2
+ %uint_4 = OpConstant %uint 4
+%_arr_v2float_uint_4 = OpTypeArray %v2float %uint_4
+%pushConstants = OpTypeStruct %_arr_v2float_uint_4
+%_ptr_PushConstant_pushConstants = OpTypePointer PushConstant %pushConstants
+%u_pushConstants = OpVariable %_ptr_PushConstant_pushConstants PushConstant
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_VertexIndex = OpVariable %_ptr_Input_int Input
+%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float
+ %float_0 = OpConstant %float 0
+ %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %24 = OpLoad %int %gl_VertexIndex
+ %26 = OpAccessChain %_ptr_PushConstant_v2float %u_pushConstants %int_0 %24
+ %27 = OpLoad %v2float %26
+ %30 = OpCompositeExtract %float %27 0
+ %31 = OpCompositeExtract %float %27 1
+ %32 = OpCompositeConstruct %v4float %30 %31 %float_0 %float_1
+ %34 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %34 %32
+ OpReturn
+ OpFunctionEnd
+[fragment shader]
+#version 430
+layout(location = 0) out vec4 outColor;
+void main() {
+ outColor = vec4(0.5, 0.5, 0.5, 0.5);
+}
+
+[test]
+clear
+# Draw over bottom left quadrant
+uniform float 0 -1.0 -1.0 0.0 -1.0 -1.0 0.0 0.0 0.0
+draw rect -1 -1 2 2
+
+probe rect rgba (0, 0, 125, 125) (0.5 0.5 0.5 0.5)
+probe rect rgba (125, 125, 125, 125) (0.0 0.0 0.0 0.0)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader spirv]
+; Test a vertex shader with an SSBO in the OpEntryPoint instruction.
+;
+; #version 450
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; vec2 in_data[3];
+; };
+;
+; void main() {
+; gl_Position = vec4(in_data[gl_VertexIndex], 0.0, 1.0);
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %_ %__0 %gl_VertexIndex
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_data"
+ OpName %__0 ""
+ OpName %gl_VertexIndex "gl_VertexIndex"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %_arr_v2float_uint_3 ArrayStride 8
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ OpDecorate %gl_VertexIndex BuiltIn VertexIndex
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+ %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %v2float = OpTypeVector %float 2
+ %uint_3 = OpConstant %uint 3
+%_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3
+%input_buffer = OpTypeStruct %_arr_v2float_uint_3
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_VertexIndex = OpVariable %_ptr_Input_int Input
+%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
+ %float_0 = OpConstant %float 0
+ %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %24 = OpLoad %int %gl_VertexIndex
+ %26 = OpAccessChain %_ptr_StorageBuffer_v2float %__0 %int_0 %24
+ %27 = OpLoad %v2float %26
+ %30 = OpCompositeExtract %float %27 0
+ %31 = OpCompositeExtract %float %27 1
+ %32 = OpCompositeConstruct %v4float %30 %31 %float_0 %float_1
+ %34 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %34 %32
+ OpReturn
+ OpFunctionEnd
+[fragment shader]
+#version 430
+layout(location = 0) out vec4 outColor;
+void main() {
+ outColor = vec4(0.5, 0.5, 0.5, 0.5);
+}
+
+[vertex data]
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+[test]
+ssbo 0:0 subdata float 0 -1.0 -1.0 1.0 -1.0 -1.0 1.0
+clear
+draw arrays TRIANGLE_LIST 0 3
+
+probe rect rgba (0, 0, 125, 125) (0.5 0.5 0.5 0.5)
+probe rect rgba (125, 125, 125, 125) (0.0 0.0 0.0 0.0)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader spirv]
+; Test a vertex shader with a ubo on the OpEntryPoint.
+;
+; #version 450
+;
+; layout(binding = 0) uniform input_buffer
+; {
+; vec2 in_data[3];
+; };
+;
+; void main() {
+; gl_Position = vec4(in_data[gl_VertexIndex], 0.0, 1.0);
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %_ %__0 %gl_VertexIndex
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %_ ""
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_data"
+ OpName %__0 ""
+ OpName %gl_VertexIndex "gl_VertexIndex"
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %_arr_v2float_uint_3 ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ OpDecorate %gl_VertexIndex BuiltIn VertexIndex
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+ %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %v2float = OpTypeVector %float 2
+ %uint_3 = OpConstant %uint 3
+%_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3
+%input_buffer = OpTypeStruct %_arr_v2float_uint_3
+%_ptr_Uniform_input_buffer = OpTypePointer Uniform %input_buffer
+ %__0 = OpVariable %_ptr_Uniform_input_buffer Uniform
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_VertexIndex = OpVariable %_ptr_Input_int Input
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+ %float_0 = OpConstant %float 0
+ %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %24 = OpLoad %int %gl_VertexIndex
+ %26 = OpAccessChain %_ptr_Uniform_v2float %__0 %int_0 %24
+ %27 = OpLoad %v2float %26
+ %30 = OpCompositeExtract %float %27 0
+ %31 = OpCompositeExtract %float %27 1
+ %32 = OpCompositeConstruct %v4float %30 %31 %float_0 %float_1
+ %34 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %34 %32
+ OpReturn
+ OpFunctionEnd
+[fragment shader]
+#version 430
+layout(location = 0) out vec4 outColor;
+void main() {
+ outColor = vec4(0.5, 0.5, 0.5, 0.5);
+}
+
+[vertex data]
+ 0/R8G8_SNORM 1/R8G8B8_UNORM
+ -128 -128 255 0 0
+ 127 127 255 0 0
+ -128 127 255 0 0
+
+[test]
+uniform ubo 0:0 float 0 -1.0 -1.0 0.0 0.0 1.0 -1.0 0.0 0.0 -1.0 1.0
+clear
+draw arrays TRIANGLE_LIST 0 3
+
+probe rect rgba (0, 0, 125, 125) (0.5 0.5 0.5 0.5)
+probe rect rgba (125, 125, 125, 125) (0.0 0.0 0.0 0.0)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Test that the HlslCounterBufferGOOGLE/CounterBuffer decoration is accepted.
+; Generated with
+;
+;
+; RWStructuredBuffer<uint4> sbuf_rw_i;
+; RWStructuredBuffer<uint4> sbuf_rw_d;
+;
+; void main()
+; {
+; sbuf_rw_i[0].x = sbuf_rw_i.IncrementCounter();
+; sbuf_rw_d[0].x = sbuf_rw_d.DecrementCounter();
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %sbuf_rw_i_0 %sbuf_rw_i_count_0 %sbuf_rw_d %sbuf_rw_d_count
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %sbuf_rw_i "sbuf_rw_i"
+ OpMemberName %sbuf_rw_i 0 "@data"
+ OpName %sbuf_rw_i_0 "sbuf_rw_i"
+ OpName %sbuf_rw_i_count "sbuf_rw_i@count"
+ OpMemberName %sbuf_rw_i_count 0 "@count"
+ OpName %sbuf_rw_i_count_0 "sbuf_rw_i@count"
+ OpName %sbuf_rw_d "sbuf_rw_d"
+ OpName %sbuf_rw_d_count "sbuf_rw_d@count"
+ OpDecorate %_runtimearr_v4uint ArrayStride 16
+ OpMemberDecorate %sbuf_rw_i 0 Offset 0
+ OpDecorate %sbuf_rw_i Block
+ OpDecorate %sbuf_rw_i_0 DescriptorSet 0
+ OpDecorate %sbuf_rw_i_0 Binding 0
+ OpMemberDecorate %sbuf_rw_i_count 0 Offset 0
+ OpDecorate %sbuf_rw_i_count Block
+ OpDecorate %sbuf_rw_i_count_0 DescriptorSet 0
+ OpDecorate %sbuf_rw_i_count_0 Binding 1
+ OpDecorate %sbuf_rw_d DescriptorSet 0
+ OpDecorate %sbuf_rw_d Binding 2
+ OpDecorate %sbuf_rw_d_count DescriptorSet 0
+ OpDecorate %sbuf_rw_d_count Binding 3
+ OpDecorateId %sbuf_rw_i_0 CounterBuffer %sbuf_rw_i_count_0
+ OpDecorateId %sbuf_rw_d CounterBuffer %sbuf_rw_d_count
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %v4uint = OpTypeVector %uint 4
+%_runtimearr_v4uint = OpTypeRuntimeArray %v4uint
+ %sbuf_rw_i = OpTypeStruct %_runtimearr_v4uint
+%_ptr_StorageBuffer_sbuf_rw_i = OpTypePointer StorageBuffer %sbuf_rw_i
+%sbuf_rw_i_0 = OpVariable %_ptr_StorageBuffer_sbuf_rw_i StorageBuffer
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%sbuf_rw_i_count = OpTypeStruct %uint
+%_ptr_StorageBuffer_sbuf_rw_i_count = OpTypePointer StorageBuffer %sbuf_rw_i_count
+%sbuf_rw_i_count_0 = OpVariable %_ptr_StorageBuffer_sbuf_rw_i_count StorageBuffer
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+ %sbuf_rw_d = OpVariable %_ptr_StorageBuffer_sbuf_rw_i StorageBuffer
+%sbuf_rw_d_count = OpVariable %_ptr_StorageBuffer_sbuf_rw_i_count StorageBuffer
+%uint_4294967295 = OpConstant %uint 4294967295
+ %int_n1 = OpConstant %int -1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_uint %sbuf_rw_i_count_0 %int_0
+ %35 = OpAtomicIAdd %uint %34 %uint_1 %uint_0 %uint_1
+ %36 = OpAccessChain %_ptr_StorageBuffer_uint %sbuf_rw_i_0 %int_0 %int_0 %uint_0
+ OpStore %36 %35
+ %37 = OpAccessChain %_ptr_StorageBuffer_uint %sbuf_rw_d_count %int_0
+ %38 = OpAtomicIAdd %uint %37 %uint_1 %uint_0 %uint_4294967295
+ %39 = OpIAdd %uint %38 %int_n1
+ %40 = OpAccessChain %_ptr_StorageBuffer_uint %sbuf_rw_d %int_0 %int_0 %uint_0
+ OpStore %40 %39
+ OpReturn
+ OpFunctionEnd
+[test]
+# sbuf_rw_i_0
+ssbo 0:0 16
+# sbuf_rw_i_count_0
+ssbo 0:1 4
+# sbuf_rw_d
+ssbo 0:2 16
+# sbuf_rw_d_count
+ssbo 0:3 4
+
+ssbo 0:0 subdata uint 0 200 200 200 200
+ssbo 0:1 subdata uint 0 8
+ssbo 0:2 subdata uint 0 200 200 200 200
+ssbo 0:3 subdata uint 0 8
+
+compute entrypoint main
+compute 1 1 1
+
+# Check the storage buffer.
+probe ssbo uint 0:0 0 == 8 200 200 200
+probe ssbo uint 0:2 0 == 7 200 200 200
+
+# Check the counters.
+probe ssbo uint 0:1 0 == 9
+probe ssbo uint 0:3 0 == 7
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Test that OpDecorateStringGOOGLE/OpDecorateString is accepted.
+; Generated with
+;
+; float4 main(uint pos : FOO) : SV_Target0
+; {
+; float4 result = 0.5;
+; return result;
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %pos %_entryPointOutput
+ OpExecutionMode %main OriginUpperLeft
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %pos "pos"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpDecorate %pos Flat
+ OpDecorate %pos Location 0
+ OpDecorateString %pos UserSemantic "FOO"
+ OpDecorate %_entryPointOutput Location 0
+ OpDecorateString %_entryPointOutput UserSemantic "SV_TARGET0"
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %float_0_5 = OpConstant %float 0.5
+ %17 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
+%_ptr_Input_uint = OpTypePointer Input %uint
+ %pos = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpStore %_entryPointOutput %17
+ OpReturn
+ OpFunctionEnd
+[test]
+draw rect -1 -1 2 2
+
+probe rect rgba (0, 0, 250, 250) (0.5, 0.5, 0.5, 0.5)
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Use the IterationMultiple loop control.
+; Generated from with modified loop control:
+;
+; #version 430
+;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; int in_size;
+; ivec4 data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_size;
+; ivec4 out_SSBO[];
+; };
+;
+; void main() {
+; for( int i = 0; i < in_size; ++i ) {
+; out_SSBO[i] = data_SSBO[i];
+; }
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %i "i"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_size"
+ OpMemberName %input_buffer 1 "data_SSBO"
+ OpName %_ ""
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_size"
+ OpMemberName %output_buffer 1 "out_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_v4int ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpMemberDecorate %input_buffer 1 Offset 16
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %_runtimearr_v4int_0 ArrayStride 16
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpMemberDecorate %output_buffer 1 Offset 16
+ OpDecorate %output_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %v4int = OpTypeVector %int 4
+%_runtimearr_v4int = OpTypeRuntimeArray %v4int
+%input_buffer = OpTypeStruct %int %_runtimearr_v4int
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+%_runtimearr_v4int_0 = OpTypeRuntimeArray %v4int
+%output_buffer = OpTypeStruct %int %_runtimearr_v4int_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v4int = OpTypePointer StorageBuffer %v4int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 IterationMultiple 3
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %23 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0
+ %24 = OpLoad %int %23
+ %26 = OpSLessThan %bool %15 %24
+ OpBranchConditional %26 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %33 = OpLoad %int %i
+ %35 = OpAccessChain %_ptr_StorageBuffer_v4int %_ %int_1 %33
+ %36 = OpLoad %v4int %35
+ %37 = OpAccessChain %_ptr_StorageBuffer_v4int %__0 %int_1 %32
+ OpStore %37 %36
+ OpBranch %13
+ %13 = OpLabel
+ %38 = OpLoad %int %i
+ %39 = OpIAdd %int %38 %int_1
+ OpStore %i %39
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+[test]
+ssbo 0:0 112
+ssbo 0:0 subdata int 0 6 0 0 0
+ssbo 0:0 subdata int 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ssbo 0:1 112
+ssbo 0:1 subdata int 0 6 0 0 0
+ssbo 0:1 subdata int 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 16 == 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Use the MaxIterations loop control.
+; Generated from with modified loop control:
+;
+; #version 430
+;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; int in_size;
+; ivec4 data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_size;
+; ivec4 out_SSBO[];
+; };
+;
+; void main() {
+; for( int i = 0; i < in_size; ++i ) {
+; out_SSBO[i] = data_SSBO[i];
+; }
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %i "i"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_size"
+ OpMemberName %input_buffer 1 "data_SSBO"
+ OpName %_ ""
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_size"
+ OpMemberName %output_buffer 1 "out_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_v4int ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpMemberDecorate %input_buffer 1 Offset 16
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %_runtimearr_v4int_0 ArrayStride 16
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpMemberDecorate %output_buffer 1 Offset 16
+ OpDecorate %output_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %v4int = OpTypeVector %int 4
+%_runtimearr_v4int = OpTypeRuntimeArray %v4int
+%input_buffer = OpTypeStruct %int %_runtimearr_v4int
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+%_runtimearr_v4int_0 = OpTypeRuntimeArray %v4int
+%output_buffer = OpTypeStruct %int %_runtimearr_v4int_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v4int = OpTypePointer StorageBuffer %v4int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 MaxIterations 6
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %23 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0
+ %24 = OpLoad %int %23
+ %26 = OpSLessThan %bool %15 %24
+ OpBranchConditional %26 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %33 = OpLoad %int %i
+ %35 = OpAccessChain %_ptr_StorageBuffer_v4int %_ %int_1 %33
+ %36 = OpLoad %v4int %35
+ %37 = OpAccessChain %_ptr_StorageBuffer_v4int %__0 %int_1 %32
+ OpStore %37 %36
+ OpBranch %13
+ %13 = OpLabel
+ %38 = OpLoad %int %i
+ %39 = OpIAdd %int %38 %int_1
+ OpStore %i %39
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+[test]
+ssbo 0:0 112
+ssbo 0:0 subdata int 0 6 0 0 0
+ssbo 0:0 subdata int 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ssbo 0:1 112
+ssbo 0:1 subdata int 0 6 0 0 0
+ssbo 0:1 subdata int 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 16 == 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Use the MinIterations loop control.
+; Generated from with modified loop control:
+;
+; #version 430
+;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; int in_size;
+; ivec4 data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_size;
+; ivec4 out_SSBO[];
+; };
+;
+; void main() {
+; for( int i = 0; i < in_size; ++i ) {
+; out_SSBO[i] = data_SSBO[i];
+; }
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %i "i"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_size"
+ OpMemberName %input_buffer 1 "data_SSBO"
+ OpName %_ ""
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_size"
+ OpMemberName %output_buffer 1 "out_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_v4int ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpMemberDecorate %input_buffer 1 Offset 16
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %_runtimearr_v4int_0 ArrayStride 16
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpMemberDecorate %output_buffer 1 Offset 16
+ OpDecorate %output_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %v4int = OpTypeVector %int 4
+%_runtimearr_v4int = OpTypeRuntimeArray %v4int
+%input_buffer = OpTypeStruct %int %_runtimearr_v4int
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+%_runtimearr_v4int_0 = OpTypeRuntimeArray %v4int
+%output_buffer = OpTypeStruct %int %_runtimearr_v4int_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v4int = OpTypePointer StorageBuffer %v4int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 MinIterations 4
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %23 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0
+ %24 = OpLoad %int %23
+ %26 = OpSLessThan %bool %15 %24
+ OpBranchConditional %26 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %33 = OpLoad %int %i
+ %35 = OpAccessChain %_ptr_StorageBuffer_v4int %_ %int_1 %33
+ %36 = OpLoad %v4int %35
+ %37 = OpAccessChain %_ptr_StorageBuffer_v4int %__0 %int_1 %32
+ OpStore %37 %36
+ OpBranch %13
+ %13 = OpLabel
+ %38 = OpLoad %int %i
+ %39 = OpIAdd %int %38 %int_1
+ OpStore %i %39
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+[test]
+ssbo 0:0 112
+ssbo 0:0 subdata int 0 6 0 0 0
+ssbo 0:0 subdata int 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ssbo 0:1 112
+ssbo 0:1 subdata int 0 6 0 0 0
+ssbo 0:1 subdata int 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 16 == 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Use the PartialCount loop control.
+; Generated from with modified loop control:
+;
+; #version 430
+;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; int in_size;
+; ivec4 data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_size;
+; ivec4 out_SSBO[];
+; };
+;
+; void main() {
+; for( int i = 0; i < in_size; ++i ) {
+; out_SSBO[i] = data_SSBO[i];
+; }
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %i "i"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_size"
+ OpMemberName %input_buffer 1 "data_SSBO"
+ OpName %_ ""
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_size"
+ OpMemberName %output_buffer 1 "out_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_v4int ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpMemberDecorate %input_buffer 1 Offset 16
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %_runtimearr_v4int_0 ArrayStride 16
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpMemberDecorate %output_buffer 1 Offset 16
+ OpDecorate %output_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %v4int = OpTypeVector %int 4
+%_runtimearr_v4int = OpTypeRuntimeArray %v4int
+%input_buffer = OpTypeStruct %int %_runtimearr_v4int
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+%_runtimearr_v4int_0 = OpTypeRuntimeArray %v4int
+%output_buffer = OpTypeStruct %int %_runtimearr_v4int_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v4int = OpTypePointer StorageBuffer %v4int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 PartialCount 4
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %23 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0
+ %24 = OpLoad %int %23
+ %26 = OpSLessThan %bool %15 %24
+ OpBranchConditional %26 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %33 = OpLoad %int %i
+ %35 = OpAccessChain %_ptr_StorageBuffer_v4int %_ %int_1 %33
+ %36 = OpLoad %v4int %35
+ %37 = OpAccessChain %_ptr_StorageBuffer_v4int %__0 %int_1 %32
+ OpStore %37 %36
+ OpBranch %13
+ %13 = OpLabel
+ %38 = OpLoad %int %i
+ %39 = OpIAdd %int %38 %int_1
+ OpStore %i %39
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+[test]
+ssbo 0:0 112
+ssbo 0:0 subdata int 0 6 0 0 0
+ssbo 0:0 subdata int 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ssbo 0:1 112
+ssbo 0:1 subdata int 0 6 0 0 0
+ssbo 0:1 subdata int 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 16 == 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Use the PeelCount loop control.
+; Generated from with modified loop control:
+;
+; #version 430
+;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; int in_size;
+; ivec4 data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; int out_size;
+; ivec4 out_SSBO[];
+; };
+;
+; void main() {
+; for( int i = 0; i < in_size; ++i ) {
+; out_SSBO[i] = data_SSBO[i];
+; }
+; }
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %i "i"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "in_size"
+ OpMemberName %input_buffer 1 "data_SSBO"
+ OpName %_ ""
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_size"
+ OpMemberName %output_buffer 1 "out_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_v4int ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpMemberDecorate %input_buffer 1 Offset 16
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %_runtimearr_v4int_0 ArrayStride 16
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpMemberDecorate %output_buffer 1 Offset 16
+ OpDecorate %output_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %v4int = OpTypeVector %int 4
+%_runtimearr_v4int = OpTypeRuntimeArray %v4int
+%input_buffer = OpTypeStruct %int %_runtimearr_v4int
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+%_runtimearr_v4int_0 = OpTypeRuntimeArray %v4int
+%output_buffer = OpTypeStruct %int %_runtimearr_v4int_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v4int = OpTypePointer StorageBuffer %v4int
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ OpStore %i %int_0
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 PeelCount 2
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %int %i
+ %23 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0
+ %24 = OpLoad %int %23
+ %26 = OpSLessThan %bool %15 %24
+ OpBranchConditional %26 %11 %12
+ %11 = OpLabel
+ %32 = OpLoad %int %i
+ %33 = OpLoad %int %i
+ %35 = OpAccessChain %_ptr_StorageBuffer_v4int %_ %int_1 %33
+ %36 = OpLoad %v4int %35
+ %37 = OpAccessChain %_ptr_StorageBuffer_v4int %__0 %int_1 %32
+ OpStore %37 %36
+ OpBranch %13
+ %13 = OpLabel
+ %38 = OpLoad %int %i
+ %39 = OpIAdd %int %38 %int_1
+ OpStore %i %39
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+[test]
+ssbo 0:0 112
+ssbo 0:0 subdata int 0 6 0 0 0
+ssbo 0:0 subdata int 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ssbo 0:1 112
+ssbo 0:1 subdata int 0 6 0 0 0
+ssbo 0:1 subdata int 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 16 == 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %out_var %in_var %gid_var
+OpExecutionMode %main LocalSize 4 4 1
+
+OpDecorate %uint_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %func_var NonWritable
+
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%uint3 = OpTypeVector %uint 3
+%uint_0 = OpConstant %uint 0
+%uint_1 = OpConstant %uint 1
+%uint_2 = OpConstant %uint 2
+%uint_3 = OpConstant %uint 3
+%uint_4 = OpConstant %uint 4
+%uint_5 = OpConstant %uint 5
+%uint_6 = OpConstant %uint 6
+%uint_7 = OpConstant %uint 7
+%uint_8 = OpConstant %uint 8
+%uint_9 = OpConstant %uint 9
+%uint_10 = OpConstant %uint 10
+%uint_11 = OpConstant %uint 11
+%uint_12 = OpConstant %uint 12
+%uint_13 = OpConstant %uint 13
+%uint_14 = OpConstant %uint 14
+%uint_15 = OpConstant %uint 15
+%uint_array_4 = OpTypeArray %uint %uint_4
+%array_array_4 = OpTypeArray %uint_array_4 %uint_4
+
+%const_array_r_0 = OpConstantComposite %uint_array_4 %uint_15 %uint_14 %uint_13 %uint_12
+%const_array_r_1 = OpConstantComposite %uint_array_4 %uint_11 %uint_10 %uint_9 %uint_8
+%const_array_r_2 = OpConstantComposite %uint_array_4 %uint_7 %uint_6 %uint_5 %uint_4
+%const_array_r_3 = OpConstantComposite %uint_array_4 %uint_3 %uint_2 %uint_1 %uint_0
+%const_array_r = OpConstantComposite %array_array_4 %const_array_r_0 %const_array_r_1 %const_array_r_2 %const_array_r_3
+
+%ptr_array_array_function = OpTypePointer Function %array_array_4
+%ptr_func_uint = OpTypePointer Function %uint
+%uint_rta = OpTypeRuntimeArray %uint
+%struct = OpTypeStruct %uint_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_uint = OpTypePointer StorageBuffer %uint
+%ptr_input_uint3 = OpTypePointer Input %uint3
+%gid_var = OpVariable %ptr_input_uint3 Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%func_var = OpVariable %ptr_array_array_function Function %const_array_r
+%gid = OpLoad %uint3 %gid_var
+%gid_x = OpCompositeExtract %uint %gid 0
+%gid_y = OpCompositeExtract %uint %gid 1
+%x_modifier = OpIMul %uint %gid_x %uint_4
+%idx = OpIAdd %uint %x_modifier %gid_y
+%in_gep = OpAccessChain %ptr_ssbo_uint %in_var %uint_0 %idx
+%ld1 = OpLoad %uint %in_gep
+%v_gep = OpAccessChain %ptr_func_uint %func_var %gid_x %gid_y
+%ld2 = OpLoad %uint %v_gep
+%add = OpIAdd %uint %ld1 %ld2
+%out_gep = OpAccessChain %ptr_ssbo_uint %out_var %uint_0 %idx
+OpStore %out_gep %add
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ssbo 0:1 64
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 16 16 16 16
+probe ssbo uint 0:1 16 == 16 16 16 16
+probe ssbo uint 0:1 32 == 16 16 16 16
+probe ssbo uint 0:1 48 == 16 16 16 16
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %uint_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+OpDecorate %func_var1 NonWritable
+OpDecorate %func_var2 NonWritable
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%uint_1 = OpConstant %uint 1
+%uint_2 = OpConstant %uint 2
+%uint_3 = OpConstant %uint 3
+%uint_4 = OpConstant %uint 4
+%uint_5 = OpConstant %uint 5
+%uint_6 = OpConstant %uint 6
+%uint_7 = OpConstant %uint 7
+%uint_8 = OpConstant %uint 8
+%uint_9 = OpConstant %uint 9
+%uint_10 = OpConstant %uint 10
+%uint_11 = OpConstant %uint 11
+%uint_12 = OpConstant %uint 12
+%uint_13 = OpConstant %uint 13
+%uint_14 = OpConstant %uint 14
+%uint_15 = OpConstant %uint 15
+%uint_array_4 = OpTypeArray %uint %uint_4
+%array_array_4 = OpTypeArray %uint_array_4 %uint_4
+
+%const_array_f_0 = OpConstantComposite %uint_array_4 %uint_0 %uint_1 %uint_2 %uint_3
+%const_array_f_1 = OpConstantComposite %uint_array_4 %uint_4 %uint_5 %uint_6 %uint_7
+%const_array_f_2 = OpConstantComposite %uint_array_4 %uint_8 %uint_9 %uint_10 %uint_11
+%const_array_f_3 = OpConstantComposite %uint_array_4 %uint_12 %uint_13 %uint_14 %uint_15
+%const_array_f = OpConstantComposite %array_array_4 %const_array_f_0 %const_array_f_1 %const_array_f_2 %const_array_f_3
+
+%const_array_r_0 = OpConstantComposite %uint_array_4 %uint_15 %uint_14 %uint_13 %uint_12
+%const_array_r_1 = OpConstantComposite %uint_array_4 %uint_11 %uint_10 %uint_9 %uint_8
+%const_array_r_2 = OpConstantComposite %uint_array_4 %uint_7 %uint_6 %uint_5 %uint_4
+%const_array_r_3 = OpConstantComposite %uint_array_4 %uint_3 %uint_2 %uint_1 %uint_0
+%const_array_r = OpConstantComposite %array_array_4 %const_array_r_0 %const_array_r_1 %const_array_r_2 %const_array_r_3
+
+%ptr_array_array_function = OpTypePointer Function %array_array_4
+%ptr_func_uint = OpTypePointer Function %uint
+%uint_rta = OpTypeRuntimeArray %uint
+%struct = OpTypeStruct %uint_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_uint = OpTypePointer StorageBuffer %uint
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%func_var1 = OpVariable %ptr_array_array_function Function %const_array_f
+%func_var2 = OpVariable %ptr_array_array_function Function %const_array_r
+OpBranch %outer_loop
+
+%outer_loop = OpLabel
+%i = OpPhi %uint %uint_0 %entry %inc_i %outer_latch
+%inc_i = OpIAdd %uint %i %uint_1
+%outer_eq = OpIEqual %bool %inc_i %uint_4
+OpLoopMerge %outer_merge %outer_latch None
+OpBranch %inner_loop
+
+%inner_loop = OpLabel
+%j = OpPhi %uint %uint_0 %outer_loop %inc_j %inner_loop
+%inc_j = OpIAdd %uint %j %uint_1
+%v1_gep = OpAccessChain %ptr_func_uint %func_var1 %i %j
+%ld1 = OpLoad %uint %v1_gep
+%v2_gep = OpAccessChain %ptr_func_uint %func_var2 %i %j
+%ld2 = OpLoad %uint %v2_gep
+%add = OpIAdd %uint %ld1 %ld2
+%i_modifier = OpIMul %uint %i %uint_4
+%out_idx = OpIAdd %uint %i_modifier %j
+%out_gep = OpAccessChain %ptr_ssbo_uint %out_var %uint_0 %out_idx
+OpStore %out_gep %add
+%inner_eq = OpIEqual %bool %inc_j %uint_4
+OpLoopMerge %outer_latch %inner_loop None
+OpBranchConditional %inner_eq %outer_latch %inner_loop
+
+%outer_latch = OpLabel
+OpBranchConditional %outer_eq %outer_merge %outer_loop
+
+%outer_merge = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 64
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:0 0 == 15 15 15 15
+probe ssbo uint 0:0 16 == 15 15 15 15
+probe ssbo uint 0:0 32 == 15 15 15 15
+probe ssbo uint 0:0 48 == 15 15 15 15
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %out_var %in_var %gid_var %priv_var
+OpExecutionMode %main LocalSize 4 4 1
+
+OpDecorate %uint_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %priv_var NonWritable
+
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%uint3 = OpTypeVector %uint 3
+%uint_0 = OpConstant %uint 0
+%uint_1 = OpConstant %uint 1
+%uint_2 = OpConstant %uint 2
+%uint_3 = OpConstant %uint 3
+%uint_4 = OpConstant %uint 4
+%uint_5 = OpConstant %uint 5
+%uint_6 = OpConstant %uint 6
+%uint_7 = OpConstant %uint 7
+%uint_8 = OpConstant %uint 8
+%uint_9 = OpConstant %uint 9
+%uint_10 = OpConstant %uint 10
+%uint_11 = OpConstant %uint 11
+%uint_12 = OpConstant %uint 12
+%uint_13 = OpConstant %uint 13
+%uint_14 = OpConstant %uint 14
+%uint_15 = OpConstant %uint 15
+%uint_array_4 = OpTypeArray %uint %uint_4
+%array_array_4 = OpTypeArray %uint_array_4 %uint_4
+
+%const_array_r_0 = OpConstantComposite %uint_array_4 %uint_15 %uint_14 %uint_13 %uint_12
+%const_array_r_1 = OpConstantComposite %uint_array_4 %uint_11 %uint_10 %uint_9 %uint_8
+%const_array_r_2 = OpConstantComposite %uint_array_4 %uint_7 %uint_6 %uint_5 %uint_4
+%const_array_r_3 = OpConstantComposite %uint_array_4 %uint_3 %uint_2 %uint_1 %uint_0
+%const_array_r = OpConstantComposite %array_array_4 %const_array_r_0 %const_array_r_1 %const_array_r_2 %const_array_r_3
+
+%ptr_array_array_private = OpTypePointer Private %array_array_4
+%ptr_priv_uint = OpTypePointer Private %uint
+%uint_rta = OpTypeRuntimeArray %uint
+%struct = OpTypeStruct %uint_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_uint = OpTypePointer StorageBuffer %uint
+%ptr_input_uint3 = OpTypePointer Input %uint3
+%gid_var = OpVariable %ptr_input_uint3 Input
+%priv_var = OpVariable %ptr_array_array_private Private %const_array_r
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid = OpLoad %uint3 %gid_var
+%gid_x = OpCompositeExtract %uint %gid 0
+%gid_y = OpCompositeExtract %uint %gid 1
+%x_modifier = OpIMul %uint %gid_x %uint_4
+%idx = OpIAdd %uint %x_modifier %gid_y
+%in_gep = OpAccessChain %ptr_ssbo_uint %in_var %uint_0 %idx
+%ld1 = OpLoad %uint %in_gep
+%v_gep = OpAccessChain %ptr_priv_uint %priv_var %gid_x %gid_y
+%ld2 = OpLoad %uint %v_gep
+%add = OpIAdd %uint %ld1 %ld2
+%out_gep = OpAccessChain %ptr_ssbo_uint %out_var %uint_0 %idx
+OpStore %out_gep %add
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ssbo 0:1 64
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 16 16 16 16
+probe ssbo uint 0:1 16 == 16 16 16 16
+probe ssbo uint 0:1 32 == 16 16 16 16
+probe ssbo uint 0:1 48 == 16 16 16 16
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %out_var %priv_var1 %priv_var2
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %uint_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+OpDecorate %priv_var1 NonWritable
+OpDecorate %priv_var2 NonWritable
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%uint_1 = OpConstant %uint 1
+%uint_2 = OpConstant %uint 2
+%uint_3 = OpConstant %uint 3
+%uint_4 = OpConstant %uint 4
+%uint_5 = OpConstant %uint 5
+%uint_6 = OpConstant %uint 6
+%uint_7 = OpConstant %uint 7
+%uint_8 = OpConstant %uint 8
+%uint_9 = OpConstant %uint 9
+%uint_10 = OpConstant %uint 10
+%uint_11 = OpConstant %uint 11
+%uint_12 = OpConstant %uint 12
+%uint_13 = OpConstant %uint 13
+%uint_14 = OpConstant %uint 14
+%uint_15 = OpConstant %uint 15
+%uint_array_4 = OpTypeArray %uint %uint_4
+%array_array_4 = OpTypeArray %uint_array_4 %uint_4
+
+%const_array_f_0 = OpConstantComposite %uint_array_4 %uint_0 %uint_1 %uint_2 %uint_3
+%const_array_f_1 = OpConstantComposite %uint_array_4 %uint_4 %uint_5 %uint_6 %uint_7
+%const_array_f_2 = OpConstantComposite %uint_array_4 %uint_8 %uint_9 %uint_10 %uint_11
+%const_array_f_3 = OpConstantComposite %uint_array_4 %uint_12 %uint_13 %uint_14 %uint_15
+%const_array_f = OpConstantComposite %array_array_4 %const_array_f_0 %const_array_f_1 %const_array_f_2 %const_array_f_3
+
+%const_array_r_0 = OpConstantComposite %uint_array_4 %uint_15 %uint_14 %uint_13 %uint_12
+%const_array_r_1 = OpConstantComposite %uint_array_4 %uint_11 %uint_10 %uint_9 %uint_8
+%const_array_r_2 = OpConstantComposite %uint_array_4 %uint_7 %uint_6 %uint_5 %uint_4
+%const_array_r_3 = OpConstantComposite %uint_array_4 %uint_3 %uint_2 %uint_1 %uint_0
+%const_array_r = OpConstantComposite %array_array_4 %const_array_r_0 %const_array_r_1 %const_array_r_2 %const_array_r_3
+
+%ptr_array_array_private = OpTypePointer Private %array_array_4
+%priv_var1 = OpVariable %ptr_array_array_private Private %const_array_f
+%priv_var2 = OpVariable %ptr_array_array_private Private %const_array_r
+%ptr_priv_uint = OpTypePointer Private %uint
+%uint_rta = OpTypeRuntimeArray %uint
+%struct = OpTypeStruct %uint_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_uint = OpTypePointer StorageBuffer %uint
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpBranch %outer_loop
+
+%outer_loop = OpLabel
+%i = OpPhi %uint %uint_0 %entry %inc_i %outer_latch
+%inc_i = OpIAdd %uint %i %uint_1
+%outer_eq = OpIEqual %bool %inc_i %uint_4
+OpLoopMerge %outer_merge %outer_latch None
+OpBranch %inner_loop
+
+%inner_loop = OpLabel
+%j = OpPhi %uint %uint_0 %outer_loop %inc_j %inner_loop
+%inc_j = OpIAdd %uint %j %uint_1
+%v1_gep = OpAccessChain %ptr_priv_uint %priv_var1 %i %j
+%ld1 = OpLoad %uint %v1_gep
+%v2_gep = OpAccessChain %ptr_priv_uint %priv_var2 %i %j
+%ld2 = OpLoad %uint %v2_gep
+%add = OpIAdd %uint %ld1 %ld2
+%i_modifier = OpIMul %uint %i %uint_4
+%out_idx = OpIAdd %uint %i_modifier %j
+%out_gep = OpAccessChain %ptr_ssbo_uint %out_var %uint_0 %out_idx
+OpStore %out_gep %add
+%inner_eq = OpIEqual %bool %inc_j %uint_4
+OpLoopMerge %outer_latch %inner_loop None
+OpBranchConditional %inner_eq %outer_latch %inner_loop
+
+%outer_latch = OpLabel
+OpBranchConditional %outer_eq %outer_merge %outer_loop
+
+%outer_merge = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 64
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:0 0 == 15 15 15 15
+probe ssbo uint 0:0 16 == 15 15 15 15
+probe ssbo uint 0:0 32 == 15 15 15 15
+probe ssbo uint 0:0 48 == 15 15 15 15
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %ssbo
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpMemberDecorate %struct 1 Offset 16
+OpMemberDecorate %struct 2 Offset 32
+OpMemberDecorate %struct 3 Offset 48
+OpMemberDecorate %struct 4 Offset 64
+OpDecorate %ssbo DescriptorSet 0
+OpDecorate %ssbo Binding 0
+
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_4 = OpConstant %int 4
+%int4 = OpTypeVector %int 4
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+
+%struct = OpTypeStruct %int4 %int %int %int %int
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%ssbo = OpVariable %ptr_ssbo_struct StorageBuffer
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%src_gep0 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_0
+%dst_gep0 = OpAccessChain %ptr_ssbo_int %ssbo %int_1
+OpCopyMemory %dst_gep0 %src_gep0 Aligned 16 Aligned 4
+%src_gep1 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_1
+%dst_gep1 = OpAccessChain %ptr_ssbo_int %ssbo %int_2
+OpCopyMemory %dst_gep1 %src_gep1 Aligned 16 Aligned 4
+%src_gep2 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_2
+%dst_gep2 = OpAccessChain %ptr_ssbo_int %ssbo %int_3
+OpCopyMemory %dst_gep2 %src_gep2 Aligned 16 Aligned 4
+%src_gep3 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_3
+%dst_gep3 = OpAccessChain %ptr_ssbo_int %ssbo %int_4
+OpCopyMemory %dst_gep3 %src_gep3 Aligned 16 Aligned 4
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 68
+ssbo 0:0 subdata uint 0 1 2 3 4
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:0 16 == 1
+probe ssbo uint 0:0 32 == 2
+probe ssbo uint 0:0 48 == 3
+probe ssbo uint 0:0 64 == 4
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %ssbo
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpMemberDecorate %struct 1 Offset 16
+OpMemberDecorate %struct 2 Offset 32
+OpMemberDecorate %struct 3 Offset 48
+OpMemberDecorate %struct 4 Offset 64
+OpDecorate %ssbo DescriptorSet 0
+OpDecorate %ssbo Binding 0
+
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_4 = OpConstant %int 4
+%int4 = OpTypeVector %int 4
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+
+%struct = OpTypeStruct %int4 %int %int %int %int
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%ssbo = OpVariable %ptr_ssbo_struct StorageBuffer
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%src_gep0 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_0
+%dst_gep0 = OpAccessChain %ptr_ssbo_int %ssbo %int_1
+OpCopyMemory %dst_gep0 %src_gep0 Aligned 16 None
+%src_gep1 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_1
+%dst_gep1 = OpAccessChain %ptr_ssbo_int %ssbo %int_2
+OpCopyMemory %dst_gep1 %src_gep1 Aligned 16 None
+%src_gep2 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_2
+%dst_gep2 = OpAccessChain %ptr_ssbo_int %ssbo %int_3
+OpCopyMemory %dst_gep2 %src_gep2 Aligned 16 None
+%src_gep3 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_3
+%dst_gep3 = OpAccessChain %ptr_ssbo_int %ssbo %int_4
+OpCopyMemory %dst_gep3 %src_gep3 Aligned 16 None
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 68
+ssbo 0:0 subdata uint 0 1 2 3 4
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:0 16 == 1
+probe ssbo uint 0:0 32 == 2
+probe ssbo uint 0:0 48 == 3
+probe ssbo uint 0:0 64 == 4
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %ssbo
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpMemberDecorate %struct 1 Offset 16
+OpMemberDecorate %struct 2 Offset 32
+OpMemberDecorate %struct 3 Offset 48
+OpMemberDecorate %struct 4 Offset 64
+OpDecorate %ssbo DescriptorSet 0
+OpDecorate %ssbo Binding 0
+
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_4 = OpConstant %int 4
+%int4 = OpTypeVector %int 4
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+
+%struct = OpTypeStruct %int4 %int %int %int %int
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%ssbo = OpVariable %ptr_ssbo_struct StorageBuffer
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%src_gep0 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_0
+%dst_gep0 = OpAccessChain %ptr_ssbo_int %ssbo %int_1
+OpCopyMemory %dst_gep0 %src_gep0 None Aligned 4
+%src_gep1 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_1
+%dst_gep1 = OpAccessChain %ptr_ssbo_int %ssbo %int_2
+OpCopyMemory %dst_gep1 %src_gep1 None Aligned 4
+%src_gep2 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_2
+%dst_gep2 = OpAccessChain %ptr_ssbo_int %ssbo %int_3
+OpCopyMemory %dst_gep2 %src_gep2 None Aligned 4
+%src_gep3 = OpAccessChain %ptr_ssbo_int %ssbo %int_0 %int_3
+%dst_gep3 = OpAccessChain %ptr_ssbo_int %ssbo %int_4
+OpCopyMemory %dst_gep3 %src_gep3 None Aligned 4
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 68
+ssbo 0:0 subdata uint 0 1 2 3 4
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:0 16 == 1
+probe ssbo uint 0:0 32 == 2
+probe ssbo uint 0:0 48 == 3
+probe ssbo uint 0:0 64 == 4
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Test operates on a SSBO (%in_var) containing a runtime array of an array of four ints.
+; Size of the runtime array is passed another SSBO (%n_var).
+
+; Each invocation writes out the result of OpPtrDiff
+; for elements of the input runtime array to index 16 of the corresponding output
+; variable. Pointers are based the gid'th element vs the zero'th element.
+
+; Each invocation loops 4 times and writes out results each for OpPtrDiff.
+; The pointers are the lid'th element of gid'th element of
+; the runtime array vs the iteration count element of the gid'th element of
+; the runtime array.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %diff_var %n_var %input_var
+OpExecutionMode %main LocalSize 4 1 1
+
+OpDecorate %struct_4 Block
+OpMemberDecorate %struct_4 0 Offset 0
+OpDecorate %runtime_4 ArrayStride 16
+OpDecorate %struct_17 Block
+OpMemberDecorate %struct_17 0 Offset 0
+OpDecorate %runtime_17 ArrayStride 68
+OpDecorate %n_struct Block
+OpMemberDecorate %n_struct 0 Offset 0
+OpDecorate %array_4 ArrayStride 4
+OpDecorate %array_17 ArrayStride 4
+
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %diff_var DescriptorSet 0
+OpDecorate %diff_var Binding 1
+OpDecorate %n_var DescriptorSet 0
+OpDecorate %n_var Binding 2
+
+OpDecorate %input_struct Block
+OpMemberDecorate %input_struct 0 BuiltIn LocalInvocationId
+OpMemberDecorate %input_struct 1 BuiltIn WorkgroupId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%int_16 = OpConstant %int 16
+%int_17 = OpConstant %int 17
+%int3 = OpTypeVector %int 3
+
+%input_struct = OpTypeStruct %int3 %int3
+%ptr_input_struct = OpTypePointer Input %input_struct
+%ptr_input_int3 = OpTypePointer Input %int3
+
+%array_4 = OpTypeArray %int %int_4
+%runtime_4 = OpTypeRuntimeArray %array_4
+%struct_4 = OpTypeStruct %runtime_4
+%ptr_struct_4 = OpTypePointer StorageBuffer %struct_4
+%ptr_array_4 = OpTypePointer StorageBuffer %array_4
+
+%array_17 = OpTypeArray %int %int_17
+%runtime_17 = OpTypeRuntimeArray %array_17
+%struct_17 = OpTypeStruct %runtime_17
+%ptr_struct_17 = OpTypePointer StorageBuffer %struct_17
+%ptr_array_17 = OpTypePointer StorageBuffer %array_17
+
+%ptr_int = OpTypePointer StorageBuffer %int
+%n_struct = OpTypeStruct %int
+%ptr_n_struct = OpTypePointer Uniform %n_struct
+%ptr_n = OpTypePointer Uniform %int
+
+%in_var = OpVariable %ptr_struct_4 StorageBuffer
+%diff_var = OpVariable %ptr_struct_17 StorageBuffer
+%n_var = OpVariable %ptr_n_struct Uniform
+%input_var = OpVariable %ptr_input_struct Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_n %n_var %int_0
+%n = OpLoad %int %n_gep
+%gid_gep = OpAccessChain %ptr_input_int3 %input_var %int_1
+%gid = OpLoad %int3 %gid_gep
+%gid_x = OpCompositeExtract %int %gid 0
+%lid_gep = OpAccessChain %ptr_input_int3 %input_var %int_0
+%lid = OpLoad %int3 %lid_gep
+%lid_x = OpCompositeExtract %int %lid 0
+%array_gep_0 = OpAccessChain %ptr_array_4 %in_var %int_0 %int_0
+%array_gep = OpAccessChain %ptr_array_4 %in_var %int_0 %gid_x
+%cmp_gid = OpSGreaterThanEqual %bool %gid_x %n
+OpSelectionMerge %body None
+OpBranchConditional %cmp_gid %ret %body
+
+%ret = OpLabel
+OpReturn
+
+%body = OpLabel
+%cmp_lid = OpIEqual %bool %lid_x %int_1
+OpSelectionMerge %loop None
+OpBranchConditional %cmp_lid %then %loop
+
+%then = OpLabel
+; Compute results for outer array
+%large_diff = OpPtrDiff %int %array_gep %array_gep_0
+%large_diff_gep = OpAccessChain %ptr_int %diff_var %int_0 %gid_x %int_16
+OpStore %large_diff_gep %large_diff
+;
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %body %int_0 %then %inc_i %loop
+%inc_i = OpIAdd %int %i %int_1
+%i_cmp = OpIEqual %bool %inc_i %int_4
+%lid_offset = OpIMul %int %lid_x %int_4
+%gep_offset = OpIAdd %int %lid_offset %i
+; Compute results for inner array
+%ref_gep = OpAccessChain %ptr_int %array_gep %lid_x
+%cmp_gep = OpAccessChain %ptr_int %array_gep %i
+%diff = OpPtrDiff %int %ref_gep %cmp_gep
+%diff_gep = OpAccessChain %ptr_int %diff_var %int_0 %gid_x %gep_offset
+OpStore %diff_gep %diff
+;
+OpLoopMerge %exit %loop None
+OpBranchConditional %i_cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 2048
+ssbo 0:1 2176
+uniform ubo 0:2 int 0 32
+
+compute entrypoint main
+compute 32 1 1
+
+# diff var
+probe ssbo int 0:1 0 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 0
+probe ssbo int 0:1 68 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 1
+probe ssbo int 0:1 136 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 2
+probe ssbo int 0:1 204 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 3
+probe ssbo int 0:1 272 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 4
+probe ssbo int 0:1 340 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 5
+probe ssbo int 0:1 408 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 6
+probe ssbo int 0:1 476 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 7
+probe ssbo int 0:1 544 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 8
+probe ssbo int 0:1 612 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 9
+probe ssbo int 0:1 680 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 10
+probe ssbo int 0:1 748 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 11
+probe ssbo int 0:1 816 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 12
+probe ssbo int 0:1 884 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 13
+probe ssbo int 0:1 952 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 14
+probe ssbo int 0:1 1020 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 15
+probe ssbo int 0:1 1088 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 16
+probe ssbo int 0:1 1156 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 17
+probe ssbo int 0:1 1224 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 18
+probe ssbo int 0:1 1292 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 19
+probe ssbo int 0:1 1360 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 20
+probe ssbo int 0:1 1428 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 21
+probe ssbo int 0:1 1496 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 22
+probe ssbo int 0:1 1564 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 23
+probe ssbo int 0:1 1632 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 24
+probe ssbo int 0:1 1700 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 25
+probe ssbo int 0:1 1768 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 26
+probe ssbo int 0:1 1836 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 27
+probe ssbo int 0:1 1904 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 28
+probe ssbo int 0:1 1972 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 29
+probe ssbo int 0:1 2040 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 30
+probe ssbo int 0:1 2108 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 31
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests pointer comparisons with variable pointers
+
+; Stores an array of pointers in Function storage class that point into input
+; SSBO. Each iteration produces an int2 result containing two OpPtrDiffs
+; Pointers evolve by incrementing or decrementing by 1 each iteration (overall
+; ratio is 2:1).
+
+; All uses of OpPtrDiff are within %in_var, so we only need
+; VariablePointersStorageBuffer capability and the corresponding Vulkan
+; feature bit.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %int2_rta ArrayStride 8
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int2 = OpTypeVector %int 2
+
+%int_rta = OpTypeRuntimeArray %int
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%int2_rta = OpTypeRuntimeArray %int2
+%out_struct = OpTypeStruct %int2_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%array_ptr = OpTypeArray %ptr_ssbo_int %int_2
+%ptr_ptr = OpTypePointer Function %array_ptr
+%ptr_func_ptr = OpTypePointer Function %ptr_ssbo_int
+
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%var = OpVariable %ptr_ptr Function
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%length = OpArrayLength %uint %in_var 1
+%length_div_2 = OpSDiv %int %length %int_2
+%mid_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %length_div_2
+%func_gep_0 = OpAccessChain %ptr_func_ptr %var %int_0
+%func_gep_1 = OpAccessChain %ptr_func_ptr %var %int_1
+OpStore %func_gep_0 %mid_gep
+OpStore %func_gep_1 %mid_gep
+%cmp_n = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %cmp_n %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %continue
+%gep_0 = OpLoad %ptr_ssbo_int %func_gep_0
+%gep_1 = OpLoad %ptr_ssbo_int %func_gep_1
+%inc_i = OpIAdd %int %i %int_1
+
+%diff1 = OpPtrDiff %int %gep_0 %gep_1
+%diff2 = OpPtrDiff %int %gep_1 %gep_0
+%result = OpCompositeConstruct %int2 %diff1 %diff2
+%out_gep = OpAccessChain %ptr_ssbo_int2 %out_var %int_0 %i
+OpStore %out_gep %result
+
+OpLoopMerge %loop_exit %continue None
+OpBranch %body
+
+%body = OpLabel
+%i_mod_3 = OpSMod %int %i %int_3
+%cmp_vs_0 = OpIEqual %bool %i_mod_3 %int_0
+OpSelectionMerge %continue None
+OpBranchConditional %cmp_vs_0 %then %else
+
+%then = OpLabel
+%then_0_next = OpPtrAccessChain %ptr_ssbo_int %gep_0 %int_n1
+%then_1_next = OpPtrAccessChain %ptr_ssbo_int %gep_1 %int_1
+OpBranch %continue
+%else = OpLabel
+%else_0_next = OpPtrAccessChain %ptr_ssbo_int %gep_0 %int_1
+%else_1_next = OpPtrAccessChain %ptr_ssbo_int %gep_1 %int_n1
+OpBranch %continue
+
+%continue = OpLabel
+%next_0 = OpPhi %ptr_ssbo_int %then_0_next %then %else_0_next %else
+%next_1 = OpPhi %ptr_ssbo_int %then_1_next %then %else_1_next %else
+OpStore %func_gep_0 %next_0
+OpStore %func_gep_1 %next_1
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 68
+ssbo 0:0 subdata uint 0 16
+ssbo 0:1 128
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 0 0
+probe ssbo int 0:1 8 == -2 2
+probe ssbo int 0:1 16 == 0 0
+probe ssbo int 0:1 24 == 2 -2
+probe ssbo int 0:1 32 == 0 0
+probe ssbo int 0:1 40 == 2 -2
+probe ssbo int 0:1 48 == 4 -4
+probe ssbo int 0:1 56 == 2 -2
+probe ssbo int 0:1 64 == 4 -4
+probe ssbo int 0:1 72 == 6 -6
+probe ssbo int 0:1 80 == 4 -4
+probe ssbo int 0:1 88 == 6 -6
+probe ssbo int 0:1 96 == 8 -8
+probe ssbo int 0:1 104 == 6 -6
+probe ssbo int 0:1 112 == 8 -8
+probe ssbo int 0:1 120 == 10 -10
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests use of private variables holding SSBO pointers and pointer comparisons.
+
+; Two iterators are each stored in Private variables: one moves forward, one
+; moves backward. In each iteration an int2 result is written that contains two
+; diffs. Iterators are then moved forward (or backward respectively) one index.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var %forward_var %backward_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %int2_rta ArrayStride 8
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int2 = OpTypeVector %int 2
+
+%int_rta = OpTypeRuntimeArray %int
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%int2_rta = OpTypeRuntimeArray %int2
+%out_struct = OpTypeStruct %int2_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%ptr_ptr = OpTypePointer Private %ptr_ssbo_int
+%forward_var = OpVariable %ptr_ptr Private
+%backward_var = OpVariable %ptr_ptr Private
+
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%first_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %int_0
+OpStore %forward_var %first_gep
+%last_gep = OpPtrAccessChain %ptr_ssbo_int %first_gep %n
+OpStore %backward_var %last_gep
+%cmp_n = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %cmp_n %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%forward_gep = OpLoad %ptr_ssbo_int %forward_var
+%backward_gep = OpLoad %ptr_ssbo_int %backward_var
+%forward_next = OpPtrAccessChain %ptr_ssbo_int %forward_gep %int_1
+%backward_next = OpPtrAccessChain %ptr_ssbo_int %backward_gep %int_n1
+%inc_i = OpIAdd %int %i %int_1
+OpStore %forward_var %forward_next
+OpStore %backward_var %backward_next
+
+%diff1 = OpPtrDiff %int %forward_gep %backward_gep
+%diff2 = OpPtrDiff %int %backward_gep %forward_gep
+%result = OpCompositeConstruct %int2 %diff1 %diff2
+%out_gep = OpAccessChain %ptr_ssbo_int2 %out_var %int_0 %i
+OpStore %out_gep %result
+
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpLoopMerge %loop_exit %loop None
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+# Only data for number of iterations matters.
+ssbo 0:0 subdata int 0 33
+ssbo 0:1 264
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo ivec2 0:1 0 == -33 33
+probe ssbo ivec2 0:1 8 == -31 31
+probe ssbo ivec2 0:1 16 == -29 29
+probe ssbo ivec2 0:1 24 == -27 27
+probe ssbo ivec2 0:1 32 == -25 25
+probe ssbo ivec2 0:1 40 == -23 23
+probe ssbo ivec2 0:1 48 == -21 21
+probe ssbo ivec2 0:1 56 == -19 19
+probe ssbo ivec2 0:1 64 == -17 17
+probe ssbo ivec2 0:1 72 == -15 15
+probe ssbo ivec2 0:1 80 == -13 13
+probe ssbo ivec2 0:1 88 == -11 11
+probe ssbo ivec2 0:1 96 == -9 9
+probe ssbo ivec2 0:1 104 == -7 7
+probe ssbo ivec2 0:1 112 == -5 5
+probe ssbo ivec2 0:1 120 == -3 3
+probe ssbo ivec2 0:1 128 == -1 1
+probe ssbo ivec2 0:1 136 == 1 -1
+probe ssbo ivec2 0:1 144 == 3 -3
+probe ssbo ivec2 0:1 152 == 5 -5
+probe ssbo ivec2 0:1 160 == 7 -7
+probe ssbo ivec2 0:1 168 == 9 -9
+probe ssbo ivec2 0:1 176 == 11 -11
+probe ssbo ivec2 0:1 184 == 13 -13
+probe ssbo ivec2 0:1 192 == 15 -15
+probe ssbo ivec2 0:1 200 == 17 -17
+probe ssbo ivec2 0:1 208 == 19 -19
+probe ssbo ivec2 0:1 216 == 21 -21
+probe ssbo ivec2 0:1 224 == 23 -23
+probe ssbo ivec2 0:1 232 == 25 -25
+probe ssbo ivec2 0:1 240 == 27 -27
+probe ssbo ivec2 0:1 248 == 29 -29
+probe ssbo ivec2 0:1 256 == 31 -31
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests use of private variables holding workgroup pointers and pointer comparisons.
+
+; Two iterators are each stored in Private variables: one moves forward, one
+; moves backward. In each iteration an int2 result is written that contains
+; two diffs (operands swapped). Iterators are then moved forward (or backward
+; respectively) one index.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var %forward_var %backward_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int2_rta ArrayStride 8
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+OpDecorate %ptr_wg_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_32 = OpConstant %int 32
+%int2 = OpTypeVector %int 2
+
+%int_array_32 = OpTypeArray %int %int_32
+%ptr_wg_array = OpTypePointer Workgroup %int_array_32
+%wg_var = OpVariable %ptr_wg_array Workgroup
+
+%int2_rta = OpTypeRuntimeArray %int2
+%out_struct = OpTypeStruct %int2_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_wg_int = OpTypePointer Workgroup %int
+%ptr_ptr = OpTypePointer Private %ptr_wg_int
+%forward_var = OpVariable %ptr_ptr Private
+%backward_var = OpVariable %ptr_ptr Private
+
+%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%first_gep = OpAccessChain %ptr_wg_int %wg_var %int_0
+OpStore %forward_var %first_gep
+%last_gep = OpPtrAccessChain %ptr_wg_int %first_gep %int_32
+OpStore %backward_var %last_gep
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%forward_gep = OpLoad %ptr_wg_int %forward_var
+%backward_gep = OpLoad %ptr_wg_int %backward_var
+%forward_next = OpPtrAccessChain %ptr_wg_int %forward_gep %int_1
+%backward_next = OpPtrAccessChain %ptr_wg_int %backward_gep %int_n1
+%inc_i = OpIAdd %int %i %int_1
+OpStore %forward_var %forward_next
+OpStore %backward_var %backward_next
+
+%diff1 = OpPtrDiff %int %forward_gep %backward_gep
+%diff2 = OpPtrDiff %int %backward_gep %forward_gep
+%result = OpCompositeConstruct %int2 %diff1 %diff2
+%out_gep = OpAccessChain %ptr_ssbo_int2 %out_var %int_0 %i
+OpStore %out_gep %result
+
+%cmp = OpSGreaterThan %bool %i %int_32
+OpLoopMerge %exit %loop None
+OpBranchConditional %cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 264
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo ivec2 0:0 0 == -32 32
+probe ssbo ivec2 0:0 8 == -30 30
+probe ssbo ivec2 0:0 16 == -28 28
+probe ssbo ivec2 0:0 24 == -26 26
+probe ssbo ivec2 0:0 32 == -24 24
+probe ssbo ivec2 0:0 40 == -22 22
+probe ssbo ivec2 0:0 48 == -20 20
+probe ssbo ivec2 0:0 56 == -18 18
+probe ssbo ivec2 0:0 64 == -16 16
+probe ssbo ivec2 0:0 72 == -14 14
+probe ssbo ivec2 0:0 80 == -12 12
+probe ssbo ivec2 0:0 88 == -10 10
+probe ssbo ivec2 0:0 96 == -8 8
+probe ssbo ivec2 0:0 104 == -6 6
+probe ssbo ivec2 0:0 112 == -4 4
+probe ssbo ivec2 0:0 120 == -2 2
+probe ssbo ivec2 0:0 128 == 0 0
+probe ssbo ivec2 0:0 136 == 2 -2
+probe ssbo ivec2 0:0 144 == 4 -4
+probe ssbo ivec2 0:0 152 == 6 -6
+probe ssbo ivec2 0:0 160 == 8 -8
+probe ssbo ivec2 0:0 168 == 10 -10
+probe ssbo ivec2 0:0 176 == 12 -12
+probe ssbo ivec2 0:0 184 == 14 -14
+probe ssbo ivec2 0:0 192 == 16 -16
+probe ssbo ivec2 0:0 200 == 18 -18
+probe ssbo ivec2 0:0 208 == 20 -20
+probe ssbo ivec2 0:0 216 == 22 -22
+probe ssbo ivec2 0:0 224 == 24 -24
+probe ssbo ivec2 0:0 232 == 26 -26
+probe ssbo ivec2 0:0 240 == 28 -28
+probe ssbo ivec2 0:0 248 == 30 -30
+probe ssbo ivec2 0:0 256 == 32 -32
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Test operates on a Workgroup array (%wg_var) containing an array of 16 arrays of four ints.
+
+; Each invocation writes out the result of OpPtrDiff for elements of the
+; outer array to index 16 of the corresponding output variable. Pointers are
+; based the gid'th element vs the zero'th element.
+
+; Each invocation loops 4 times and writes out 4 results each for OpPtrDiff.
+; The pointers are the lid'th element of gid'th element of the outer array vs
+; the iteration count mod 4'th element of the gid'th element of the outer
+; array. Results are ordered so each thread writes continguous results.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %diff_var %input_var
+OpExecutionMode %main LocalSize 16 4 1
+
+OpDecorate %struct_17 Block
+OpMemberDecorate %struct_17 0 Offset 0
+OpDecorate %runtime_17 ArrayStride 68
+OpDecorate %array_17 ArrayStride 4
+
+OpDecorate %diff_var DescriptorSet 0
+OpDecorate %diff_var Binding 0
+
+OpDecorate %input_struct Block
+OpMemberDecorate %input_struct 0 BuiltIn LocalInvocationId
+OpMemberDecorate %input_struct 1 BuiltIn GlobalInvocationId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%int_16 = OpConstant %int 16
+%int_17 = OpConstant %int 17
+%int_64 = OpConstant %int 64
+%int3 = OpTypeVector %int 3
+
+%input_struct = OpTypeStruct %int3 %int3
+%ptr_input_struct = OpTypePointer Input %input_struct
+%ptr_input_int3 = OpTypePointer Input %int3
+
+%array_4 = OpTypeArray %int %int_4
+%array_array_4 = OpTypeArray %array_4 %int_16
+%ptr_array_array_4 = OpTypePointer Workgroup %array_array_4
+%ptr_array_4 = OpTypePointer Workgroup %array_4
+%ptr_wg_int = OpTypePointer Workgroup %int
+
+%array_17 = OpTypeArray %int %int_17
+%runtime_17 = OpTypeRuntimeArray %array_17
+%struct_17 = OpTypeStruct %runtime_17
+%ptr_struct_17 = OpTypePointer StorageBuffer %struct_17
+%ptr_array_17 = OpTypePointer StorageBuffer %array_17
+%ptr_int = OpTypePointer StorageBuffer %int
+
+%wg_var = OpVariable %ptr_array_array_4 Workgroup
+%diff_var = OpVariable %ptr_struct_17 StorageBuffer
+%input_var = OpVariable %ptr_input_struct Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid_gep = OpAccessChain %ptr_input_int3 %input_var %int_1
+%gid = OpLoad %int3 %gid_gep
+%gid_x = OpCompositeExtract %int %gid 0
+%gid_y = OpCompositeExtract %int %gid 1
+%lid_gep = OpAccessChain %ptr_input_int3 %input_var %int_0
+%lid = OpLoad %int3 %lid_gep
+%lid_x = OpCompositeExtract %int %lid 0
+%lid_y = OpCompositeExtract %int %lid 1
+%array_gep_0 = OpAccessChain %ptr_array_4 %wg_var %int_0
+%array_gep = OpAccessChain %ptr_array_4 %wg_var %lid_x
+%lid_y_is_1 = OpIEqual %bool %lid_y %int_1
+OpSelectionMerge %loop None
+OpBranchConditional %lid_y_is_1 %then %loop
+
+%then = OpLabel
+; Compute results for outer array
+%large_diff = OpPtrDiff %int %array_gep %array_gep_0
+%large_diff_gep = OpAccessChain %ptr_int %diff_var %int_0 %gid_x %int_16
+OpStore %large_diff_gep %large_diff
+;
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %int_0 %then %inc_i %loop
+%inc_i = OpIAdd %int %i %int_1
+%i_cmp = OpIEqual %bool %inc_i %int_4
+%lid_offset = OpIMul %int %lid_y %int_4
+%out_gep_index = OpIAdd %int %i %lid_offset
+; Compute results for inner array
+%ref_gep = OpAccessChain %ptr_wg_int %array_gep %lid_y
+%cmp_gep = OpAccessChain %ptr_wg_int %array_gep %i
+%diff = OpPtrDiff %int %ref_gep %cmp_gep
+%diff_gep = OpAccessChain %ptr_int %diff_var %int_0 %gid_x %out_gep_index
+OpStore %diff_gep %diff
+;
+OpLoopMerge %exit %loop None
+OpBranchConditional %i_cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+
+[test]
+# 16 x 4 x 2 = 128 work items
+# 4 x 4 = 16 bytes per invocation
+# 2048 bytes from looping
+# 16 x 2 = 32 coarse results (1 per lid)
+# 128 bytes
+# 2176 total bytes
+ssbo 0:0 2176
+
+compute entrypoint main
+compute 2 1 1
+
+# diff var
+probe ssbo int 0:0 0 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 0
+probe ssbo int 0:0 68 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 1
+probe ssbo int 0:0 136 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 2
+probe ssbo int 0:0 204 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 3
+probe ssbo int 0:0 272 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 4
+probe ssbo int 0:0 340 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 5
+probe ssbo int 0:0 408 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 6
+probe ssbo int 0:0 476 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 7
+probe ssbo int 0:0 544 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 8
+probe ssbo int 0:0 612 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 9
+probe ssbo int 0:0 680 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 10
+probe ssbo int 0:0 748 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 11
+probe ssbo int 0:0 816 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 12
+probe ssbo int 0:0 884 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 13
+probe ssbo int 0:0 952 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 14
+probe ssbo int 0:0 1020 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 15
+probe ssbo int 0:0 1088 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 0
+probe ssbo int 0:0 1156 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 1
+probe ssbo int 0:0 1224 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 2
+probe ssbo int 0:0 1292 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 3
+probe ssbo int 0:0 1360 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 4
+probe ssbo int 0:0 1428 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 5
+probe ssbo int 0:0 1496 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 6
+probe ssbo int 0:0 1564 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 7
+probe ssbo int 0:0 1632 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 8
+probe ssbo int 0:0 1700 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 9
+probe ssbo int 0:0 1768 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 10
+probe ssbo int 0:0 1836 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 11
+probe ssbo int 0:0 1904 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 12
+probe ssbo int 0:0 1972 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 13
+probe ssbo int 0:0 2040 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 14
+probe ssbo int 0:0 2108 == 0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0 15
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This test generates four results.
+
+; The results are based of OpPtrEqual comparisons of
+; %ssbo_var vs null.
+; 0: comparison of %ssbo_var vs null
+; 1: comparison of SSBO float pointer vs null
+; 2: comparison of null struct vs null struct
+; 3: comparison of null float vs null float
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %ssbo_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %ssbo_struct Block
+OpMemberDecorate %ssbo_struct 0 Offset 0
+OpDecorate %ssbo_var DescriptorSet 0
+OpDecorate %ssbo_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%float = OpTypeFloat 32
+%int = OpTypeInt 32 0
+%int4 = OpTypeVector %int 4
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+
+%ssbo_struct = OpTypeStruct %float
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %ssbo_struct
+%ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_float = OpTypePointer StorageBuffer %float
+
+%out_struct = OpTypeStruct %int4
+%ptr_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_out_struct StorageBuffer
+%ptr_ssbo_int4 = OpTypePointer StorageBuffer %int4
+
+%ptr_ssbo_struct_null = OpConstantNull %ptr_ssbo_struct
+%ptr_ssbo_float_null = OpConstantNull %ptr_ssbo_float
+%ptr_ssbo_struct_null2 = OpConstantNull %ptr_ssbo_struct
+%ptr_ssbo_float_null2 = OpConstantNull %ptr_ssbo_float
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+
+%ssbo_equal = OpPtrEqual %bool %ssbo_var %ptr_ssbo_struct_null
+%ssbo_equal_int = OpSelect %int %ssbo_equal %int_1 %int_0
+
+%ssbo_gep_0 = OpAccessChain %ptr_ssbo_float %ssbo_var %int_0
+%ssbo_equal_0 = OpPtrEqual %bool %ssbo_gep_0 %ptr_ssbo_float_null
+%ssbo_equal_0_int = OpSelect %int %ssbo_equal_0 %int_1 %int_0
+
+%null_ssbo_equal = OpPtrEqual %bool %ptr_ssbo_struct_null %ptr_ssbo_struct_null2
+%null_ssbo_equal_int = OpSelect %int %null_ssbo_equal %int_1 %int_0
+
+%null_ssbo_equal_0 = OpPtrEqual %bool %ptr_ssbo_float_null %ptr_ssbo_float_null2
+%null_ssbo_equal_0_int = OpSelect %int %null_ssbo_equal_0 %int_1 %int_0
+
+%combined = OpCompositeConstruct %int4 %ssbo_equal_int %ssbo_equal_0_int %null_ssbo_equal_int %null_ssbo_equal_0_int
+%out_gep = OpAccessChain %ptr_ssbo_int4 %out_var %int_0
+OpStore %out_gep %combined
+
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 16
+ssbo 0:1 16
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uvec4 0:1 0 == 0 0 1 1
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This generates 4 results for OpPtrEqual
+
+; The workgroup variable is a struct containing a single float.
+
+; Results:
+; 0: comparison of the workgroup var vs null
+; 1: comparison of the workgroup float vs null
+; 2: comparison of null struct vs null struct
+; 3: comparison of null float vs null float
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%float = OpTypeFloat 32
+%int = OpTypeInt 32 0
+%int4 = OpTypeVector %int 4
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+
+%wg_struct = OpTypeStruct %float
+%ptr_wg_struct = OpTypePointer Workgroup %wg_struct
+%wg_var = OpVariable %ptr_wg_struct Workgroup
+%ptr_wg_float = OpTypePointer Workgroup %float
+
+%out_struct = OpTypeStruct %int4
+%ptr_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_out_struct StorageBuffer
+%ptr_ssbo_int4 = OpTypePointer StorageBuffer %int4
+
+%ptr_wg_struct_null = OpConstantNull %ptr_wg_struct
+%ptr_wg_float_null = OpConstantNull %ptr_wg_float
+%ptr_wg_struct_null2 = OpConstantNull %ptr_wg_struct
+%ptr_wg_float_null2 = OpConstantNull %ptr_wg_float
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+
+%wg_equal = OpPtrEqual %bool %wg_var %ptr_wg_struct_null
+%wg_equal_int = OpSelect %int %wg_equal %int_1 %int_0
+
+%wg_gep_0 = OpAccessChain %ptr_wg_float %wg_var %int_0
+%wg_equal_0 = OpPtrEqual %bool %wg_gep_0 %ptr_wg_float_null
+%wg_equal_0_int = OpSelect %int %wg_equal_0 %int_1 %int_0
+
+%null_wg_equal = OpPtrEqual %bool %ptr_wg_struct_null %ptr_wg_struct_null2
+%null_wg_equal_int = OpSelect %int %null_wg_equal %int_1 %int_0
+
+%null_wg_equal_0 = OpPtrEqual %bool %ptr_wg_float_null %ptr_wg_float_null2
+%null_wg_equal_0_int = OpSelect %int %null_wg_equal_0 %int_1 %int_0
+
+%combined = OpCompositeConstruct %int4 %wg_equal_int %wg_equal_0_int %null_wg_equal_int %null_wg_equal_0_int
+%out_gep = OpAccessChain %ptr_ssbo_int4 %out_var %int_0
+OpStore %out_gep %combined
+
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 16
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uvec4 0:0 0 == 0 0 1 1
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Test operates on a SSBO (%in_var) containing a runtime array of an array of four ints.
+; Size of the runtime array is passed another SSBO (%n_var).
+
+; Each invocation writes out the result of OpPtrEqual
+; for elements of the input runtime array to index 16 of the corresponding output
+; variable. Pointers are based the gid'th element vs the zero'th element.
+
+; Each invocation loops 4 times and writes out results each for
+; OpPtrEqual. The pointers are the lid'th element of gid'th element of
+; the runtime array vs the iteration count element of the gid'th element of
+; the runtime array.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %equal_var %n_var %input_var
+OpExecutionMode %main LocalSize 4 1 1
+
+OpDecorate %struct_4 Block
+OpMemberDecorate %struct_4 0 Offset 0
+OpDecorate %runtime_4 ArrayStride 16
+OpDecorate %struct_17 Block
+OpMemberDecorate %struct_17 0 Offset 0
+OpDecorate %runtime_17 ArrayStride 68
+OpDecorate %n_struct Block
+OpMemberDecorate %n_struct 0 Offset 0
+OpDecorate %array_4 ArrayStride 4
+OpDecorate %array_17 ArrayStride 4
+
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %equal_var DescriptorSet 0
+OpDecorate %equal_var Binding 1
+OpDecorate %n_var DescriptorSet 0
+OpDecorate %n_var Binding 2
+
+OpDecorate %input_struct Block
+OpMemberDecorate %input_struct 0 BuiltIn LocalInvocationId
+OpMemberDecorate %input_struct 1 BuiltIn WorkgroupId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%int_16 = OpConstant %int 16
+%int_17 = OpConstant %int 17
+%int3 = OpTypeVector %int 3
+
+%input_struct = OpTypeStruct %int3 %int3
+%ptr_input_struct = OpTypePointer Input %input_struct
+%ptr_input_int3 = OpTypePointer Input %int3
+
+%array_4 = OpTypeArray %int %int_4
+%runtime_4 = OpTypeRuntimeArray %array_4
+%struct_4 = OpTypeStruct %runtime_4
+%ptr_struct_4 = OpTypePointer StorageBuffer %struct_4
+%ptr_array_4 = OpTypePointer StorageBuffer %array_4
+
+%array_17 = OpTypeArray %int %int_17
+%runtime_17 = OpTypeRuntimeArray %array_17
+%struct_17 = OpTypeStruct %runtime_17
+%ptr_struct_17 = OpTypePointer StorageBuffer %struct_17
+%ptr_array_17 = OpTypePointer StorageBuffer %array_17
+
+%ptr_int = OpTypePointer StorageBuffer %int
+%n_struct = OpTypeStruct %int
+%ptr_n_struct = OpTypePointer Uniform %n_struct
+%ptr_n = OpTypePointer Uniform %int
+
+%in_var = OpVariable %ptr_struct_4 StorageBuffer
+%equal_var = OpVariable %ptr_struct_17 StorageBuffer
+%n_var = OpVariable %ptr_n_struct Uniform
+%input_var = OpVariable %ptr_input_struct Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_n %n_var %int_0
+%n = OpLoad %int %n_gep
+%gid_gep = OpAccessChain %ptr_input_int3 %input_var %int_1
+%gid = OpLoad %int3 %gid_gep
+%gid_x = OpCompositeExtract %int %gid 0
+%lid_gep = OpAccessChain %ptr_input_int3 %input_var %int_0
+%lid = OpLoad %int3 %lid_gep
+%lid_x = OpCompositeExtract %int %lid 0
+%array_gep_0 = OpAccessChain %ptr_array_4 %in_var %int_0 %int_0
+%array_gep = OpAccessChain %ptr_array_4 %in_var %int_0 %gid_x
+%cmp_gid = OpSGreaterThanEqual %bool %gid_x %n
+OpSelectionMerge %body None
+OpBranchConditional %cmp_gid %ret %body
+
+%ret = OpLabel
+OpReturn
+
+%body = OpLabel
+%cmp_lid = OpIEqual %bool %lid_x %int_1
+OpSelectionMerge %loop None
+OpBranchConditional %cmp_lid %then %loop
+
+%then = OpLabel
+; Compute results for outer array
+%large_equal = OpPtrEqual %bool %array_gep %array_gep_0
+%large_equal_gep = OpAccessChain %ptr_int %equal_var %int_0 %gid_x %int_16
+%large_equal_int = OpSelect %int %large_equal %int_1 %int_0
+OpStore %large_equal_gep %large_equal_int
+;
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %body %int_0 %then %inc_i %loop
+%inc_i = OpIAdd %int %i %int_1
+%i_cmp = OpIEqual %bool %inc_i %int_4
+%lid_offset = OpIMul %int %lid_x %int_4
+%gep_offset = OpIAdd %int %lid_offset %i
+; Compute results for inner array
+%ref_gep = OpAccessChain %ptr_int %array_gep %lid_x
+%cmp_gep = OpAccessChain %ptr_int %array_gep %i
+%equal = OpPtrEqual %bool %ref_gep %cmp_gep
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%equal_gep = OpAccessChain %ptr_int %equal_var %int_0 %gid_x %gep_offset
+OpStore %equal_gep %equal_int
+;
+OpLoopMerge %exit %loop None
+OpBranchConditional %i_cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 2048
+ssbo 0:1 2176
+uniform ubo 0:2 int 0 32
+
+compute entrypoint main
+compute 32 1 1
+
+
+#equal var
+probe ssbo int 0:1 0 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1
+probe ssbo int 0:1 68 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 136 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 204 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 272 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 340 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 408 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 476 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 544 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 612 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 680 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 748 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 816 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 884 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 952 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1020 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1088 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1156 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1224 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1292 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1360 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1428 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1496 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1564 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1632 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1700 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1768 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1836 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1904 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 1972 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 2040 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:1 2108 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests pointer comparisons with variable pointers
+
+; Stores an array of pointers in Function storage class that point into input
+; SSBO. Each iteration produces an OpPtrEqual comparison. Pointers evolve by
+; incrementing or decrementing by 1 each iteration (overall ratio is 2:1).
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%array_ptr = OpTypeArray %ptr_ssbo_int %int_2
+%ptr_ptr = OpTypePointer Function %array_ptr
+%ptr_func_ptr = OpTypePointer Function %ptr_ssbo_int
+
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%var = OpVariable %ptr_ptr Function
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%length = OpArrayLength %uint %in_var 1
+%length_div_2 = OpSDiv %int %length %int_2
+%mid_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %length_div_2
+%func_gep_0 = OpAccessChain %ptr_func_ptr %var %int_0
+%func_gep_1 = OpAccessChain %ptr_func_ptr %var %int_1
+OpStore %func_gep_0 %mid_gep
+OpStore %func_gep_1 %mid_gep
+%cmp_n = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %cmp_n %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %continue
+%gep_0 = OpLoad %ptr_ssbo_int %func_gep_0
+%gep_1 = OpLoad %ptr_ssbo_int %func_gep_1
+%inc_i = OpIAdd %int %i %int_1
+
+%equal = OpPtrEqual %bool %gep_0 %gep_1
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %equal_int
+
+OpLoopMerge %loop_exit %continue None
+OpBranch %body
+
+%body = OpLabel
+%i_mod_3 = OpSMod %int %i %int_3
+%cmp_vs_0 = OpIEqual %bool %i_mod_3 %int_0
+OpSelectionMerge %continue None
+OpBranchConditional %cmp_vs_0 %then %else
+
+%then = OpLabel
+%then_0_next = OpPtrAccessChain %ptr_ssbo_int %gep_0 %int_n1
+%then_1_next = OpPtrAccessChain %ptr_ssbo_int %gep_1 %int_1
+OpBranch %continue
+%else = OpLabel
+%else_0_next = OpPtrAccessChain %ptr_ssbo_int %gep_0 %int_1
+%else_1_next = OpPtrAccessChain %ptr_ssbo_int %gep_1 %int_n1
+OpBranch %continue
+
+%continue = OpLabel
+%next_0 = OpPhi %ptr_ssbo_int %then_0_next %then %else_0_next %else
+%next_1 = OpPhi %ptr_ssbo_int %then_1_next %then %else_1_next %else
+OpStore %func_gep_0 %next_0
+OpStore %func_gep_1 %next_1
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 68
+ssbo 0:0 subdata uint 0 16
+ssbo 0:1 64
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This test generates four results per iteration of the loop. The loop is executed %n times.
+
+; Each iteration generates a result for OpPtrEqual. One
+; pointer is an iterator through the input SSBO (%in_var) and the other is a
+; selection between the iterator, null or the 0'th index pointer depending on
+; the value of the iterator mod 3.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int2 = OpTypeVector %int 2
+%int_rta = OpTypeRuntimeArray %int
+%int2_rta = OpTypeRuntimeArray %int2
+
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%ptr_ssbo_int_null = OpConstantNull %ptr_ssbo_int
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
+%void_fn = OpTypeFunction %void
+%ptr_return_fn = OpTypeFunction %ptr_ssbo_int %ptr_ssbo_int %ptr_ssbo_int %int
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%base_ssbo_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %int_0
+%n_leq_0 = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %n_leq_0 %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%ssbo_gep = OpPhi %ptr_ssbo_int %base_ssbo_gep %entry %next_ssbo_gep %loop
+%inc_i = OpIAdd %int %i %int_1
+%next_ssbo_gep = OpPtrAccessChain %ptr_ssbo_int %ssbo_gep %int_1
+
+%ptr_call = OpFunctionCall %ptr_ssbo_int %gep_func %ssbo_gep %base_ssbo_gep %i
+%equal = OpPtrEqual %bool %ssbo_gep %ptr_call
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %equal_int
+
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpLoopMerge %loop_exit %loop None
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+%gep_func = OpFunction %ptr_ssbo_int None %ptr_return_fn
+%param_ptr = OpFunctionParameter %ptr_ssbo_int
+%param_alt_ptr = OpFunctionParameter %ptr_ssbo_int
+%param_i = OpFunctionParameter %int
+%1 = OpLabel
+%i_mod_3 = OpSMod %int %param_i %int_3
+%i_mod_3_is_0 = OpIEqual %bool %i_mod_3 %int_0
+%i_mod_3_is_1 = OpIEqual %bool %i_mod_3 %int_1
+%ssbo_gep1 = OpSelect %ptr_ssbo_int %i_mod_3_is_0 %param_alt_ptr %ptr_ssbo_int_null
+%ssbo_gep2 = OpSelect %ptr_ssbo_int %i_mod_3_is_1 %param_ptr %ssbo_gep1
+OpReturnValue %ssbo_gep2
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+ssbo 0:0 subdata int 0 33
+ssbo 0:1 132
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests use of private variables holding SSBO pointers and pointer comparisons.
+
+; Two iterators are each stored in Private variables: one moves forward, one
+; moves backward. In each iteration an OpPtrEqual comparison is written.
+; Iterators are then moved forward (or backward respectively) one index.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var %forward_var %backward_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%ptr_ptr = OpTypePointer Private %ptr_ssbo_int
+%forward_var = OpVariable %ptr_ptr Private
+%backward_var = OpVariable %ptr_ptr Private
+
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%first_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %int_0
+OpStore %forward_var %first_gep
+%last_gep = OpPtrAccessChain %ptr_ssbo_int %first_gep %n
+OpStore %backward_var %last_gep
+%cmp_n = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %cmp_n %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%forward_gep = OpLoad %ptr_ssbo_int %forward_var
+%backward_gep = OpLoad %ptr_ssbo_int %backward_var
+%forward_next = OpPtrAccessChain %ptr_ssbo_int %forward_gep %int_1
+%backward_next = OpPtrAccessChain %ptr_ssbo_int %backward_gep %int_n1
+%inc_i = OpIAdd %int %i %int_1
+OpStore %forward_var %forward_next
+OpStore %backward_var %backward_next
+
+%equal = OpPtrEqual %bool %forward_gep %backward_gep
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %equal_int
+
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpLoopMerge %loop_exit %loop None
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+# Only data for number of iterations matters.
+ssbo 0:0 subdata int 0 32
+ssbo 0:1 128
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 0
+probe ssbo int 0:1 4 == 0
+probe ssbo int 0:1 8 == 0
+probe ssbo int 0:1 12 == 0
+probe ssbo int 0:1 16 == 0
+probe ssbo int 0:1 20 == 0
+probe ssbo int 0:1 24 == 0
+probe ssbo int 0:1 28 == 0
+probe ssbo int 0:1 32 == 0
+probe ssbo int 0:1 36 == 0
+probe ssbo int 0:1 40 == 0
+probe ssbo int 0:1 44 == 0
+probe ssbo int 0:1 48 == 0
+probe ssbo int 0:1 52 == 0
+probe ssbo int 0:1 56 == 0
+probe ssbo int 0:1 60 == 0
+probe ssbo int 0:1 64 == 1
+probe ssbo int 0:1 68 == 0
+probe ssbo int 0:1 72 == 0
+probe ssbo int 0:1 76 == 0
+probe ssbo int 0:1 80 == 0
+probe ssbo int 0:1 84 == 0
+probe ssbo int 0:1 88 == 0
+probe ssbo int 0:1 92 == 0
+probe ssbo int 0:1 96 == 0
+probe ssbo int 0:1 100 == 0
+probe ssbo int 0:1 104 == 0
+probe ssbo int 0:1 108 == 0
+probe ssbo int 0:1 112 == 0
+probe ssbo int 0:1 116 == 0
+probe ssbo int 0:1 120 == 0
+probe ssbo int 0:1 124 == 0
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests use of private variables holding workgroup pointers and pointer comparisons.
+
+; Two iterators are each stored in Private variables: one moves forward, one
+; moves backward. In each iteration an equal comparison is written. Iterators
+; are then moved forward (or backward respectively) one index.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var %forward_var %backward_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+OpDecorate %ptr_wg_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_32 = OpConstant %int 32
+
+%int_array_32 = OpTypeArray %int %int_32
+%ptr_wg_array = OpTypePointer Workgroup %int_array_32
+%wg_var = OpVariable %ptr_wg_array Workgroup
+
+%int_rta = OpTypeRuntimeArray %int
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_wg_int = OpTypePointer Workgroup %int
+%ptr_ptr = OpTypePointer Private %ptr_wg_int
+%forward_var = OpVariable %ptr_ptr Private
+%backward_var = OpVariable %ptr_ptr Private
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%first_gep = OpAccessChain %ptr_wg_int %wg_var %int_0
+OpStore %forward_var %first_gep
+%last_gep = OpPtrAccessChain %ptr_wg_int %first_gep %int_32
+OpStore %backward_var %last_gep
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%forward_gep = OpLoad %ptr_wg_int %forward_var
+%backward_gep = OpLoad %ptr_wg_int %backward_var
+%forward_next = OpPtrAccessChain %ptr_wg_int %forward_gep %int_1
+%backward_next = OpPtrAccessChain %ptr_wg_int %backward_gep %int_n1
+%inc_i = OpIAdd %int %i %int_1
+OpStore %forward_var %forward_next
+OpStore %backward_var %backward_next
+
+%equal = OpPtrEqual %bool %forward_gep %backward_gep
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %equal_int
+
+%cmp = OpSGreaterThan %bool %i %int_32
+OpLoopMerge %exit %loop None
+OpBranchConditional %cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 528
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:0 0 == 0
+probe ssbo int 0:0 4 == 0
+probe ssbo int 0:0 8 == 0
+probe ssbo int 0:0 12 == 0
+probe ssbo int 0:0 16 == 0
+probe ssbo int 0:0 20 == 0
+probe ssbo int 0:0 24 == 0
+probe ssbo int 0:0 28 == 0
+probe ssbo int 0:0 32 == 0
+probe ssbo int 0:0 36 == 0
+probe ssbo int 0:0 40 == 0
+probe ssbo int 0:0 44 == 0
+probe ssbo int 0:0 48 == 0
+probe ssbo int 0:0 52 == 0
+probe ssbo int 0:0 56 == 0
+probe ssbo int 0:0 60 == 0
+probe ssbo int 0:0 64 == 1
+probe ssbo int 0:0 68 == 0
+probe ssbo int 0:0 72 == 0
+probe ssbo int 0:0 76 == 0
+probe ssbo int 0:0 80 == 0
+probe ssbo int 0:0 84 == 0
+probe ssbo int 0:0 88 == 0
+probe ssbo int 0:0 92 == 0
+probe ssbo int 0:0 96 == 0
+probe ssbo int 0:0 100 == 0
+probe ssbo int 0:0 104 == 0
+probe ssbo int 0:0 108 == 0
+probe ssbo int 0:0 112 == 0
+probe ssbo int 0:0 116 == 0
+probe ssbo int 0:0 120 == 0
+probe ssbo int 0:0 124 == 0
+probe ssbo int 0:0 128 == 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This test generates four results per iteration of the loop. The loop is executed 64 times.
+
+; Each iteration generates results for OpPtrEqual. One pointer is an iterator
+; through the workgroup variable (%wg_var) and the other is a selection between
+; the iterator, null or the 0'th index pointer depending on the value of the
+; iterator mod 3.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %ptr_wg_int ArrayStride 4
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_32 = OpConstant %int 32
+%int_array = OpTypeArray %int %int_32
+%int_rta = OpTypeRuntimeArray %int
+
+%ptr_wg_int_array = OpTypePointer Workgroup %int_array
+%wg_var = OpVariable %ptr_wg_int_array Workgroup
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_wg_int = OpTypePointer Workgroup %int
+%ptr_wg_int_null = OpConstantNull %ptr_wg_int
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%ptr_return_fn = OpTypeFunction %ptr_wg_int %ptr_wg_int %ptr_wg_int %int
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%base_wg_gep = OpAccessChain %ptr_wg_int %wg_var %int_0
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%wg_gep = OpPhi %ptr_wg_int %base_wg_gep %entry %next_wg_gep %loop
+%inc_i = OpIAdd %int %i %int_1
+%next_wg_gep = OpPtrAccessChain %ptr_wg_int %wg_gep %int_1
+
+%ptr_call = OpFunctionCall %ptr_wg_int %gep_func %wg_gep %base_wg_gep %i
+%equal = OpPtrEqual %bool %wg_gep %ptr_call
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %equal_int
+
+%cmp = OpSGreaterThan %bool %i %int_32
+OpLoopMerge %exit %loop None
+OpBranchConditional %cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+%gep_func = OpFunction %ptr_wg_int None %ptr_return_fn
+%param_ptr = OpFunctionParameter %ptr_wg_int
+%param_alt_ptr = OpFunctionParameter %ptr_wg_int
+%param_i = OpFunctionParameter %int
+%1 = OpLabel
+%i_mod_3 = OpSMod %int %param_i %int_3
+%i_mod_3_is_0 = OpIEqual %bool %i_mod_3 %int_0
+%i_mod_3_is_1 = OpIEqual %bool %i_mod_3 %int_1
+%wg_gep1 = OpSelect %ptr_wg_int %i_mod_3_is_0 %param_alt_ptr %ptr_wg_int_null
+%wg_gep2 = OpSelect %ptr_wg_int %i_mod_3_is_1 %param_ptr %wg_gep1
+OpReturnValue %wg_gep2
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:0 0 == 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Test operates on a Workgroup array (%wg_var) containing an array of 16 arrays of four ints.
+
+; Each invocation writes out the result of OpPtrEqual for elements of the
+; outer array to index 16 of the corresponding output variable. Pointers are
+; based the gid'th element vs the zero'th element.
+
+; Each invocation loops 4 times and writes out 4 results each for OpPtrEqual.
+; The pointers are the lid'th element of gid'th element of the outer array vs
+; the iteration count mod 4'th element of the gid'th element of the outer
+; array. Results are ordered so each thread writes continguous results.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %equal_var %input_var
+OpExecutionMode %main LocalSize 16 4 1
+
+OpDecorate %struct_17 Block
+OpMemberDecorate %struct_17 0 Offset 0
+OpDecorate %runtime_17 ArrayStride 68
+OpDecorate %array_17 ArrayStride 4
+
+OpDecorate %equal_var DescriptorSet 0
+OpDecorate %equal_var Binding 0
+
+OpDecorate %input_struct Block
+OpMemberDecorate %input_struct 0 BuiltIn LocalInvocationId
+OpMemberDecorate %input_struct 1 BuiltIn GlobalInvocationId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%int_16 = OpConstant %int 16
+%int_17 = OpConstant %int 17
+%int_64 = OpConstant %int 64
+%int3 = OpTypeVector %int 3
+
+%input_struct = OpTypeStruct %int3 %int3
+%ptr_input_struct = OpTypePointer Input %input_struct
+%ptr_input_int3 = OpTypePointer Input %int3
+
+%array_4 = OpTypeArray %int %int_4
+%array_array_4 = OpTypeArray %array_4 %int_16
+%ptr_array_array_4 = OpTypePointer Workgroup %array_array_4
+%ptr_array_4 = OpTypePointer Workgroup %array_4
+%ptr_wg_int = OpTypePointer Workgroup %int
+
+%array_17 = OpTypeArray %int %int_17
+%runtime_17 = OpTypeRuntimeArray %array_17
+%struct_17 = OpTypeStruct %runtime_17
+%ptr_struct_17 = OpTypePointer StorageBuffer %struct_17
+%ptr_array_17 = OpTypePointer StorageBuffer %array_17
+%ptr_int = OpTypePointer StorageBuffer %int
+
+%wg_var = OpVariable %ptr_array_array_4 Workgroup
+%equal_var = OpVariable %ptr_struct_17 StorageBuffer
+%input_var = OpVariable %ptr_input_struct Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid_gep = OpAccessChain %ptr_input_int3 %input_var %int_1
+%gid = OpLoad %int3 %gid_gep
+%gid_x = OpCompositeExtract %int %gid 0
+%gid_y = OpCompositeExtract %int %gid 1
+%lid_gep = OpAccessChain %ptr_input_int3 %input_var %int_0
+%lid = OpLoad %int3 %lid_gep
+%lid_x = OpCompositeExtract %int %lid 0
+%lid_y = OpCompositeExtract %int %lid 1
+%array_gep_0 = OpAccessChain %ptr_array_4 %wg_var %int_0
+%array_gep = OpAccessChain %ptr_array_4 %wg_var %lid_x
+%lid_y_is_1 = OpIEqual %bool %lid_y %int_1
+OpSelectionMerge %loop None
+OpBranchConditional %lid_y_is_1 %then %loop
+
+%then = OpLabel
+; Compute results for outer array
+%large_equal = OpPtrEqual %bool %array_gep %array_gep_0
+%large_equal_gep = OpAccessChain %ptr_int %equal_var %int_0 %gid_x %int_16
+%large_equal_int = OpSelect %int %large_equal %int_1 %int_0
+OpStore %large_equal_gep %large_equal_int
+;
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %int_0 %then %inc_i %loop
+%inc_i = OpIAdd %int %i %int_1
+%i_cmp = OpIEqual %bool %inc_i %int_4
+%lid_offset = OpIMul %int %lid_y %int_4
+%out_gep_index = OpIAdd %int %i %lid_offset
+; Compute results for inner array
+%ref_gep = OpAccessChain %ptr_wg_int %array_gep %lid_y
+%cmp_gep = OpAccessChain %ptr_wg_int %array_gep %i
+%equal = OpPtrEqual %bool %ref_gep %cmp_gep
+%equal_int = OpSelect %int %equal %int_1 %int_0
+%equal_gep = OpAccessChain %ptr_int %equal_var %int_0 %gid_x %out_gep_index
+OpStore %equal_gep %equal_int
+;
+OpLoopMerge %exit %loop None
+OpBranchConditional %i_cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+
+[test]
+# 16 x 4 x 2 = 128 work items
+# 4 x 4 = 16 bytes per invocation
+# 2048 bytes from looping
+# 16 x 2 = 32 coarse results (1 per lid)
+# 128 bytes
+# 2176 total bytes
+ssbo 0:0 2176
+
+compute entrypoint main
+compute 2 1 1
+
+#equal var
+probe ssbo int 0:0 0 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1
+probe ssbo int 0:0 68 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 136 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 204 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 272 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 340 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 408 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 476 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 544 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 612 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 680 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 748 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 816 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 884 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 952 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1020 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1088 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1
+probe ssbo int 0:0 1156 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1224 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1292 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1360 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1428 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1496 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1564 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1632 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1700 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1768 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1836 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1904 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 1972 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 2040 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+probe ssbo int 0:0 2108 == 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This test generates four results.
+
+; The results are based of OpPtrNotEqual comparisons of
+; %ssbo_var vs null.
+; 0: comparison of %ssbo_var vs null
+; 1: comparison of SSBO float pointer vs null
+; 2: comparison of null struct vs null struct
+; 3: comparison of null float vs null float
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %ssbo_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %ssbo_struct Block
+OpMemberDecorate %ssbo_struct 0 Offset 0
+OpDecorate %ssbo_var DescriptorSet 0
+OpDecorate %ssbo_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%float = OpTypeFloat 32
+%int = OpTypeInt 32 0
+%int4 = OpTypeVector %int 4
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+
+%ssbo_struct = OpTypeStruct %float
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %ssbo_struct
+%ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_float = OpTypePointer StorageBuffer %float
+
+%out_struct = OpTypeStruct %int4
+%ptr_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_out_struct StorageBuffer
+%ptr_ssbo_int4 = OpTypePointer StorageBuffer %int4
+
+%ptr_ssbo_struct_null = OpConstantNull %ptr_ssbo_struct
+%ptr_ssbo_float_null = OpConstantNull %ptr_ssbo_float
+%ptr_ssbo_struct_null2 = OpConstantNull %ptr_ssbo_struct
+%ptr_ssbo_float_null2 = OpConstantNull %ptr_ssbo_float
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+
+%ssbo_not_equal = OpPtrNotEqual %bool %ssbo_var %ptr_ssbo_struct_null
+%ssbo_not_equal_int = OpSelect %int %ssbo_not_equal %int_1 %int_0
+
+%ssbo_gep_0 = OpAccessChain %ptr_ssbo_float %ssbo_var %int_0
+%ssbo_not_equal_0 = OpPtrNotEqual %bool %ssbo_gep_0 %ptr_ssbo_float_null
+%ssbo_not_equal_0_int = OpSelect %int %ssbo_not_equal_0 %int_1 %int_0
+
+%null_ssbo_not_equal = OpPtrNotEqual %bool %ptr_ssbo_struct_null %ptr_ssbo_struct_null2
+%null_ssbo_not_equal_int = OpSelect %int %null_ssbo_not_equal %int_1 %int_0
+
+%null_ssbo_not_equal_0 = OpPtrNotEqual %bool %ptr_ssbo_float_null %ptr_ssbo_float_null2
+%null_ssbo_not_equal_0_int = OpSelect %int %null_ssbo_not_equal_0 %int_1 %int_0
+
+%combined = OpCompositeConstruct %int4 %ssbo_not_equal_int %ssbo_not_equal_0_int %null_ssbo_not_equal_int %null_ssbo_not_equal_0_int
+%out_gep = OpAccessChain %ptr_ssbo_int4 %out_var %int_0
+OpStore %out_gep %combined
+
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 4
+ssbo 0:1 16
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uvec4 0:1 0 == 1 1 0 0
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This generates 4 results for OpPtrNotEqual
+
+; The workgroup variable is a struct containing a single float.
+
+; Results:
+; 0: comparison of the workgroup var vs null
+; 1: comparison of the workgroup float vs null
+; 2: comparison of null struct vs null struct
+; 3: comparison of null float vs null float
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%float = OpTypeFloat 32
+%int = OpTypeInt 32 0
+%int4 = OpTypeVector %int 4
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+
+%wg_struct = OpTypeStruct %float
+%ptr_wg_struct = OpTypePointer Workgroup %wg_struct
+%wg_var = OpVariable %ptr_wg_struct Workgroup
+%ptr_wg_float = OpTypePointer Workgroup %float
+
+%out_struct = OpTypeStruct %int4
+%ptr_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_out_struct StorageBuffer
+%ptr_ssbo_int4 = OpTypePointer StorageBuffer %int4
+
+%ptr_wg_struct_null = OpConstantNull %ptr_wg_struct
+%ptr_wg_float_null = OpConstantNull %ptr_wg_float
+%ptr_wg_struct_null2 = OpConstantNull %ptr_wg_struct
+%ptr_wg_float_null2 = OpConstantNull %ptr_wg_float
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+
+%wg_not_equal = OpPtrNotEqual %bool %wg_var %ptr_wg_struct_null
+%wg_not_equal_int = OpSelect %int %wg_not_equal %int_1 %int_0
+
+%wg_gep_0 = OpAccessChain %ptr_wg_float %wg_var %int_0
+%wg_not_equal_0 = OpPtrNotEqual %bool %wg_gep_0 %ptr_wg_float_null
+%wg_not_equal_0_int = OpSelect %int %wg_not_equal_0 %int_1 %int_0
+
+%null_wg_not_equal = OpPtrNotEqual %bool %ptr_wg_struct_null %ptr_wg_struct_null2
+%null_wg_not_equal_int = OpSelect %int %null_wg_not_equal %int_1 %int_0
+
+%null_wg_not_equal_0 = OpPtrNotEqual %bool %ptr_wg_float_null %ptr_wg_float_null2
+%null_wg_not_equal_0_int = OpSelect %int %null_wg_not_equal_0 %int_1 %int_0
+
+%combined = OpCompositeConstruct %int4 %wg_not_equal_int %wg_not_equal_0_int %null_wg_not_equal_int %null_wg_not_equal_0_int
+%out_gep = OpAccessChain %ptr_ssbo_int4 %out_var %int_0
+OpStore %out_gep %combined
+
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 16
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uvec4 0:0 0 == 1 1 0 0
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Test operates on a SSBO (%in_var) containing a runtime array of an array of four ints.
+; Size of the runtime array is passed another SSBO (%n_var).
+
+; Each invocation writes out the result of OpPtrNotEqual
+; for elements of the input runtime array to index 16 of the corresponding output
+; variable. Pointers are based the gid'th element vs the zero'th element.
+
+; Each invocation loops 4 times and writes out results each for
+; OpPtrNotEqual. The pointers are the lid'th element of gid'th element of
+; the runtime array vs the iteration count element of the gid'th element of
+; the runtime array.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %not_equal_var %n_var %input_var
+OpExecutionMode %main LocalSize 4 1 1
+
+OpDecorate %struct_4 Block
+OpMemberDecorate %struct_4 0 Offset 0
+OpDecorate %runtime_4 ArrayStride 16
+OpDecorate %struct_17 Block
+OpMemberDecorate %struct_17 0 Offset 0
+OpDecorate %runtime_17 ArrayStride 68
+OpDecorate %n_struct Block
+OpMemberDecorate %n_struct 0 Offset 0
+OpDecorate %array_4 ArrayStride 4
+OpDecorate %array_17 ArrayStride 4
+
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %not_equal_var DescriptorSet 0
+OpDecorate %not_equal_var Binding 1
+OpDecorate %n_var DescriptorSet 0
+OpDecorate %n_var Binding 2
+
+OpDecorate %input_struct Block
+OpMemberDecorate %input_struct 0 BuiltIn LocalInvocationId
+OpMemberDecorate %input_struct 1 BuiltIn WorkgroupId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%int_16 = OpConstant %int 16
+%int_17 = OpConstant %int 17
+%int3 = OpTypeVector %int 3
+
+%input_struct = OpTypeStruct %int3 %int3
+%ptr_input_struct = OpTypePointer Input %input_struct
+%ptr_input_int3 = OpTypePointer Input %int3
+
+%array_4 = OpTypeArray %int %int_4
+%runtime_4 = OpTypeRuntimeArray %array_4
+%struct_4 = OpTypeStruct %runtime_4
+%ptr_struct_4 = OpTypePointer StorageBuffer %struct_4
+%ptr_array_4 = OpTypePointer StorageBuffer %array_4
+
+%array_17 = OpTypeArray %int %int_17
+%runtime_17 = OpTypeRuntimeArray %array_17
+%struct_17 = OpTypeStruct %runtime_17
+%ptr_struct_17 = OpTypePointer StorageBuffer %struct_17
+%ptr_array_17 = OpTypePointer StorageBuffer %array_17
+
+%ptr_int = OpTypePointer StorageBuffer %int
+%n_struct = OpTypeStruct %int
+%ptr_n_struct = OpTypePointer Uniform %n_struct
+%ptr_n = OpTypePointer Uniform %int
+
+%in_var = OpVariable %ptr_struct_4 StorageBuffer
+%not_equal_var = OpVariable %ptr_struct_17 StorageBuffer
+%n_var = OpVariable %ptr_n_struct Uniform
+%input_var = OpVariable %ptr_input_struct Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_n %n_var %int_0
+%n = OpLoad %int %n_gep
+%gid_gep = OpAccessChain %ptr_input_int3 %input_var %int_1
+%gid = OpLoad %int3 %gid_gep
+%gid_x = OpCompositeExtract %int %gid 0
+%lid_gep = OpAccessChain %ptr_input_int3 %input_var %int_0
+%lid = OpLoad %int3 %lid_gep
+%lid_x = OpCompositeExtract %int %lid 0
+%array_gep_0 = OpAccessChain %ptr_array_4 %in_var %int_0 %int_0
+%array_gep = OpAccessChain %ptr_array_4 %in_var %int_0 %gid_x
+%cmp_gid = OpSGreaterThanEqual %bool %gid_x %n
+OpSelectionMerge %body None
+OpBranchConditional %cmp_gid %ret %body
+
+%ret = OpLabel
+OpReturn
+
+%body = OpLabel
+%cmp_lid = OpIEqual %bool %lid_x %int_1
+OpSelectionMerge %loop None
+OpBranchConditional %cmp_lid %then %loop
+
+%then = OpLabel
+; Compute results for outer array
+%large_not_equal = OpPtrNotEqual %bool %array_gep %array_gep_0
+%large_not_equal_gep = OpAccessChain %ptr_int %not_equal_var %int_0 %gid_x %int_16
+%large_not_equal_int = OpSelect %int %large_not_equal %int_1 %int_0
+OpStore %large_not_equal_gep %large_not_equal_int
+;
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %body %int_0 %then %inc_i %loop
+%inc_i = OpIAdd %int %i %int_1
+%i_cmp = OpIEqual %bool %inc_i %int_4
+%lid_offset = OpIMul %int %lid_x %int_4
+%gep_offset = OpIAdd %int %lid_offset %i
+; Compute results for inner array
+%ref_gep = OpAccessChain %ptr_int %array_gep %lid_x
+%cmp_gep = OpAccessChain %ptr_int %array_gep %i
+%not_equal = OpPtrNotEqual %bool %ref_gep %cmp_gep
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%not_equal_gep = OpAccessChain %ptr_int %not_equal_var %int_0 %gid_x %gep_offset
+OpStore %not_equal_gep %not_equal_int
+;
+OpLoopMerge %exit %loop None
+OpBranchConditional %i_cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 2048
+ssbo 0:1 2176
+uniform ubo 0:2 int 0 32
+
+compute entrypoint main
+compute 32 1 1
+
+#not equal var
+probe ssbo int 0:1 0 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0
+probe ssbo int 0:1 68 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 136 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 204 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 272 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 340 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 408 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 476 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 544 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 612 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 680 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 748 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 816 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 884 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 952 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1020 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1088 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1156 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1224 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1292 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1360 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1428 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1496 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1564 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1632 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1700 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1768 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1836 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1904 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 1972 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 2040 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:1 2108 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests pointer comparisons with variable pointers
+
+; Stores an array of pointers in Function storage class that point into input
+; SSBO. Each iteration produces an OpPtrNotEqual comparison. Pointers evolve by
+; incrementing or decrementing by 1 each iteration (overall ratio is 2:1).
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%uint = OpTypeInt 32 0
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%array_ptr = OpTypeArray %ptr_ssbo_int %int_2
+%ptr_ptr = OpTypePointer Function %array_ptr
+%ptr_func_ptr = OpTypePointer Function %ptr_ssbo_int
+
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%var = OpVariable %ptr_ptr Function
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%length = OpArrayLength %uint %in_var 1
+%length_div_2 = OpSDiv %int %length %int_2
+%mid_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %length_div_2
+%func_gep_0 = OpAccessChain %ptr_func_ptr %var %int_0
+%func_gep_1 = OpAccessChain %ptr_func_ptr %var %int_1
+OpStore %func_gep_0 %mid_gep
+OpStore %func_gep_1 %mid_gep
+%cmp_n = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %cmp_n %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %continue
+%gep_0 = OpLoad %ptr_ssbo_int %func_gep_0
+%gep_1 = OpLoad %ptr_ssbo_int %func_gep_1
+%inc_i = OpIAdd %int %i %int_1
+
+%not_equal = OpPtrNotEqual %bool %gep_0 %gep_1
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %not_equal_int
+
+OpLoopMerge %loop_exit %continue None
+OpBranch %body
+
+%body = OpLabel
+%i_mod_3 = OpSMod %int %i %int_3
+%cmp_vs_0 = OpIEqual %bool %i_mod_3 %int_0
+OpSelectionMerge %continue None
+OpBranchConditional %cmp_vs_0 %then %else
+
+%then = OpLabel
+%then_0_next = OpPtrAccessChain %ptr_ssbo_int %gep_0 %int_n1
+%then_1_next = OpPtrAccessChain %ptr_ssbo_int %gep_1 %int_1
+OpBranch %continue
+%else = OpLabel
+%else_0_next = OpPtrAccessChain %ptr_ssbo_int %gep_0 %int_1
+%else_1_next = OpPtrAccessChain %ptr_ssbo_int %gep_1 %int_n1
+OpBranch %continue
+
+%continue = OpLabel
+%next_0 = OpPhi %ptr_ssbo_int %then_0_next %then %else_0_next %else
+%next_1 = OpPhi %ptr_ssbo_int %then_1_next %then %else_1_next %else
+OpStore %func_gep_0 %next_0
+OpStore %func_gep_1 %next_1
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 68
+ssbo 0:0 subdata uint 0 16
+ssbo 0:1 64
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This test generates four results per iteration of the loop. The loop is executed %n times.
+
+; Each iteration generates a result for OpPtrEqual. One
+; pointer is an iterator through the input SSBO (%in_var) and the other is a
+; selection between the iterator, null or the 0'th index pointer depending on
+; the value of the iterator mod 3.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int2 = OpTypeVector %int 2
+%int_rta = OpTypeRuntimeArray %int
+%int2_rta = OpTypeRuntimeArray %int2
+
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%ptr_ssbo_int_null = OpConstantNull %ptr_ssbo_int
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
+%void_fn = OpTypeFunction %void
+%ptr_return_fn = OpTypeFunction %ptr_ssbo_int %ptr_ssbo_int %ptr_ssbo_int %int
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%base_ssbo_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %int_0
+%n_leq_0 = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %n_leq_0 %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%ssbo_gep = OpPhi %ptr_ssbo_int %base_ssbo_gep %entry %next_ssbo_gep %loop
+%inc_i = OpIAdd %int %i %int_1
+%next_ssbo_gep = OpPtrAccessChain %ptr_ssbo_int %ssbo_gep %int_1
+
+%ptr_call = OpFunctionCall %ptr_ssbo_int %gep_func %ssbo_gep %base_ssbo_gep %i
+%not_equal = OpPtrNotEqual %bool %ssbo_gep %ptr_call
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %not_equal_int
+
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpLoopMerge %loop_exit %loop None
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+%gep_func = OpFunction %ptr_ssbo_int None %ptr_return_fn
+%param_ptr = OpFunctionParameter %ptr_ssbo_int
+%param_alt_ptr = OpFunctionParameter %ptr_ssbo_int
+%param_i = OpFunctionParameter %int
+%1 = OpLabel
+%i_mod_3 = OpSMod %int %param_i %int_3
+%i_mod_3_is_0 = OpIEqual %bool %i_mod_3 %int_0
+%i_mod_3_is_1 = OpIEqual %bool %i_mod_3 %int_1
+%ssbo_gep1 = OpSelect %ptr_ssbo_int %i_mod_3_is_0 %param_alt_ptr %ptr_ssbo_int_null
+%ssbo_gep2 = OpSelect %ptr_ssbo_int %i_mod_3_is_1 %param_ptr %ssbo_gep1
+OpReturnValue %ssbo_gep2
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+ssbo 0:0 subdata int 0 33
+ssbo 0:1 132
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 0 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests use of private variables holding SSBO pointers and pointer comparisons.
+
+; Two iterators are each stored in Private variables: one moves forward, one
+; moves backward. In each iteration an OpPtrNotEqual comparison is written.
+; Iterators are then moved forward (or backward respectively) one index.
+
+OpCapability Shader
+OpCapability VariablePointersStorageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var %forward_var %backward_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %in_struct Block
+OpMemberDecorate %in_struct 0 Offset 0
+OpMemberDecorate %in_struct 1 Offset 4
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorate %ptr_ssbo_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%in_struct = OpTypeStruct %int %int_rta
+%ptr_ssbo_in_struct = OpTypePointer StorageBuffer %in_struct
+%in_var = OpVariable %ptr_ssbo_in_struct StorageBuffer
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%ptr_ptr = OpTypePointer Private %ptr_ssbo_int
+%forward_var = OpVariable %ptr_ptr Private
+%backward_var = OpVariable %ptr_ptr Private
+
+%ptr_ssbo_n = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%n_gep = OpAccessChain %ptr_ssbo_n %in_var %int_0
+%n = OpLoad %int %n_gep
+%first_gep = OpAccessChain %ptr_ssbo_int %in_var %int_1 %int_0
+OpStore %forward_var %first_gep
+%last_gep = OpPtrAccessChain %ptr_ssbo_int %first_gep %n
+OpStore %backward_var %last_gep
+%cmp_n = OpSLessThanEqual %bool %n %int_0
+OpSelectionMerge %exit None
+OpBranchConditional %cmp_n %exit %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%forward_gep = OpLoad %ptr_ssbo_int %forward_var
+%backward_gep = OpLoad %ptr_ssbo_int %backward_var
+%forward_next = OpPtrAccessChain %ptr_ssbo_int %forward_gep %int_1
+%backward_next = OpPtrAccessChain %ptr_ssbo_int %backward_gep %int_n1
+%inc_i = OpIAdd %int %i %int_1
+OpStore %forward_var %forward_next
+OpStore %backward_var %backward_next
+
+%not_equal = OpPtrNotEqual %bool %forward_gep %backward_gep
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %not_equal_int
+
+%cmp = OpSGreaterThanEqual %bool %i %n
+OpLoopMerge %loop_exit %loop None
+OpBranchConditional %cmp %loop_exit %loop
+
+%loop_exit = OpLabel
+OpBranch %exit
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+# Only data for number of iterations matters.
+ssbo 0:0 subdata int 0 32
+ssbo 0:1 128
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 1
+probe ssbo int 0:1 4 == 1
+probe ssbo int 0:1 8 == 1
+probe ssbo int 0:1 12 == 1
+probe ssbo int 0:1 16 == 1
+probe ssbo int 0:1 20 == 1
+probe ssbo int 0:1 24 == 1
+probe ssbo int 0:1 28 == 1
+probe ssbo int 0:1 32 == 1
+probe ssbo int 0:1 36 == 1
+probe ssbo int 0:1 40 == 1
+probe ssbo int 0:1 44 == 1
+probe ssbo int 0:1 48 == 1
+probe ssbo int 0:1 52 == 1
+probe ssbo int 0:1 56 == 1
+probe ssbo int 0:1 60 == 1
+probe ssbo int 0:1 64 == 0
+probe ssbo int 0:1 68 == 1
+probe ssbo int 0:1 72 == 1
+probe ssbo int 0:1 76 == 1
+probe ssbo int 0:1 80 == 1
+probe ssbo int 0:1 84 == 1
+probe ssbo int 0:1 88 == 1
+probe ssbo int 0:1 92 == 1
+probe ssbo int 0:1 96 == 1
+probe ssbo int 0:1 100 == 1
+probe ssbo int 0:1 104 == 1
+probe ssbo int 0:1 108 == 1
+probe ssbo int 0:1 112 == 1
+probe ssbo int 0:1 116 == 1
+probe ssbo int 0:1 120 == 1
+probe ssbo int 0:1 124 == 1
+
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Tests use of private variables holding workgroup pointers and pointer comparisons.
+
+; Two iterators are each stored in Private variables: one moves forward, one
+; moves backward. In each iteration a not equal comparison is written. Iterators
+; are then moved forward (or backward respectively) one index.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var %forward_var %backward_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+OpDecorate %ptr_wg_int ArrayStride 4
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_32 = OpConstant %int 32
+
+%int_array_32 = OpTypeArray %int %int_32
+%ptr_wg_array = OpTypePointer Workgroup %int_array_32
+%wg_var = OpVariable %ptr_wg_array Workgroup
+
+%int_rta = OpTypeRuntimeArray %int
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_wg_int = OpTypePointer Workgroup %int
+%ptr_ptr = OpTypePointer Private %ptr_wg_int
+%forward_var = OpVariable %ptr_ptr Private
+%backward_var = OpVariable %ptr_ptr Private
+
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%first_gep = OpAccessChain %ptr_wg_int %wg_var %int_0
+OpStore %forward_var %first_gep
+%last_gep = OpPtrAccessChain %ptr_wg_int %first_gep %int_32
+OpStore %backward_var %last_gep
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%forward_gep = OpLoad %ptr_wg_int %forward_var
+%backward_gep = OpLoad %ptr_wg_int %backward_var
+%forward_next = OpPtrAccessChain %ptr_wg_int %forward_gep %int_1
+%backward_next = OpPtrAccessChain %ptr_wg_int %backward_gep %int_n1
+%inc_i = OpIAdd %int %i %int_1
+OpStore %forward_var %forward_next
+OpStore %backward_var %backward_next
+
+%not_equal = OpPtrNotEqual %bool %forward_gep %backward_gep
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %not_equal_int
+
+%cmp = OpSGreaterThan %bool %i %int_32
+OpLoopMerge %exit %loop None
+OpBranchConditional %cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 528
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:0 0 == 1
+probe ssbo int 0:0 4 == 1
+probe ssbo int 0:0 8 == 1
+probe ssbo int 0:0 12 == 1
+probe ssbo int 0:0 16 == 1
+probe ssbo int 0:0 20 == 1
+probe ssbo int 0:0 24 == 1
+probe ssbo int 0:0 28 == 1
+probe ssbo int 0:0 32 == 1
+probe ssbo int 0:0 36 == 1
+probe ssbo int 0:0 40 == 1
+probe ssbo int 0:0 44 == 1
+probe ssbo int 0:0 48 == 1
+probe ssbo int 0:0 52 == 1
+probe ssbo int 0:0 56 == 1
+probe ssbo int 0:0 60 == 1
+probe ssbo int 0:0 64 == 0
+probe ssbo int 0:0 68 == 1
+probe ssbo int 0:0 72 == 1
+probe ssbo int 0:0 76 == 1
+probe ssbo int 0:0 80 == 1
+probe ssbo int 0:0 84 == 1
+probe ssbo int 0:0 88 == 1
+probe ssbo int 0:0 92 == 1
+probe ssbo int 0:0 96 == 1
+probe ssbo int 0:0 100 == 1
+probe ssbo int 0:0 104 == 1
+probe ssbo int 0:0 108 == 1
+probe ssbo int 0:0 112 == 1
+probe ssbo int 0:0 116 == 1
+probe ssbo int 0:0 120 == 1
+probe ssbo int 0:0 124 == 1
+probe ssbo int 0:0 128 == 1
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; This test generates four results per iteration of the loop. The loop is executed 64 times.
+
+; Each iteration generates results for OpPtrNotEqual. One pointer is an iterator
+; through the workgroup variable (%wg_var) and the other is a selection between
+; the iterator, null or the 0'th index pointer depending on the value of the
+; iterator mod 3.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %ptr_wg_int ArrayStride 4
+
+OpDecorate %out_struct Block
+OpMemberDecorate %out_struct 0 Offset 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 0
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%int_32 = OpConstant %int 32
+%int_array = OpTypeArray %int %int_32
+%int_rta = OpTypeRuntimeArray %int
+
+%ptr_wg_int_array = OpTypePointer Workgroup %int_array
+%wg_var = OpVariable %ptr_wg_int_array Workgroup
+
+%out_struct = OpTypeStruct %int_rta
+%ptr_ssbo_out_struct = OpTypePointer StorageBuffer %out_struct
+%out_var = OpVariable %ptr_ssbo_out_struct StorageBuffer
+
+%ptr_wg_int = OpTypePointer Workgroup %int
+%ptr_wg_int_null = OpConstantNull %ptr_wg_int
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%void_fn = OpTypeFunction %void
+%ptr_return_fn = OpTypeFunction %ptr_wg_int %ptr_wg_int %ptr_wg_int %int
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%base_wg_gep = OpAccessChain %ptr_wg_int %wg_var %int_0
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %inc_i %loop
+%wg_gep = OpPhi %ptr_wg_int %base_wg_gep %entry %next_wg_gep %loop
+%inc_i = OpIAdd %int %i %int_1
+%next_wg_gep = OpPtrAccessChain %ptr_wg_int %wg_gep %int_1
+
+%ptr_call = OpFunctionCall %ptr_wg_int %gep_func %wg_gep %base_wg_gep %i
+%not_equal = OpPtrNotEqual %bool %wg_gep %ptr_call ;;;; HEY THIS SHOULD BE PtrNotEqual
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %i
+OpStore %out_gep %not_equal_int
+
+%cmp = OpSGreaterThan %bool %i %int_32
+OpLoopMerge %exit %loop None
+OpBranchConditional %cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+%gep_func = OpFunction %ptr_wg_int None %ptr_return_fn
+%param_ptr = OpFunctionParameter %ptr_wg_int
+%param_alt_ptr = OpFunctionParameter %ptr_wg_int
+%param_i = OpFunctionParameter %int
+%1 = OpLabel
+%i_mod_3 = OpSMod %int %param_i %int_3
+%i_mod_3_is_0 = OpIEqual %bool %i_mod_3 %int_0
+%i_mod_3_is_1 = OpIEqual %bool %i_mod_3 %int_1
+%wg_gep1 = OpSelect %ptr_wg_int %i_mod_3_is_0 %param_alt_ptr %ptr_wg_int_null
+%wg_gep2 = OpSelect %ptr_wg_int %i_mod_3_is_1 %param_ptr %wg_gep1
+OpReturnValue %wg_gep2
+OpFunctionEnd
+
+[test]
+ssbo 0:0 132
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:0 0 == 0 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_variable_pointers
+VariablePointerFeatures.variablePointersStorageBuffer
+VariablePointerFeatures.variablePointers
+VK_KHR_storage_buffer_storage_class
+VK_KHR_get_physical_device_properties2
+
+[compute shader spirv]
+; Test operates on a Workgroup array (%wg_var) containing an array of 16 arrays of four ints.
+
+; Each invocation writes out the result of OpPtrNotEqual for elements of the
+; outer array to index 16 of the corresponding output variable. Pointers are
+; based the gid'th element vs the zero'th element.
+
+; Each invocation loops 4 times and writes out 4 results each for OpPtrNotEqual.
+; The pointers are the lid'th element of gid'th element of the outer array vs
+; the iteration count mod 4'th element of the gid'th element of the outer
+; array. Results are ordered so each thread writes continguous results.
+
+OpCapability Shader
+OpCapability VariablePointers
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %wg_var %not_equal_var %input_var
+OpExecutionMode %main LocalSize 16 4 1
+
+OpDecorate %struct_17 Block
+OpMemberDecorate %struct_17 0 Offset 0
+OpDecorate %runtime_17 ArrayStride 68
+OpDecorate %array_17 ArrayStride 4
+
+OpDecorate %not_equal_var DescriptorSet 0
+OpDecorate %not_equal_var Binding 0
+
+OpDecorate %input_struct Block
+OpMemberDecorate %input_struct 0 BuiltIn LocalInvocationId
+OpMemberDecorate %input_struct 1 BuiltIn GlobalInvocationId
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%int_16 = OpConstant %int 16
+%int_17 = OpConstant %int 17
+%int_64 = OpConstant %int 64
+%int3 = OpTypeVector %int 3
+
+%input_struct = OpTypeStruct %int3 %int3
+%ptr_input_struct = OpTypePointer Input %input_struct
+%ptr_input_int3 = OpTypePointer Input %int3
+
+%array_4 = OpTypeArray %int %int_4
+%array_array_4 = OpTypeArray %array_4 %int_16
+%ptr_array_array_4 = OpTypePointer Workgroup %array_array_4
+%ptr_array_4 = OpTypePointer Workgroup %array_4
+%ptr_wg_int = OpTypePointer Workgroup %int
+
+%array_17 = OpTypeArray %int %int_17
+%runtime_17 = OpTypeRuntimeArray %array_17
+%struct_17 = OpTypeStruct %runtime_17
+%ptr_struct_17 = OpTypePointer StorageBuffer %struct_17
+%ptr_array_17 = OpTypePointer StorageBuffer %array_17
+%ptr_int = OpTypePointer StorageBuffer %int
+
+%wg_var = OpVariable %ptr_array_array_4 Workgroup
+%not_equal_var = OpVariable %ptr_struct_17 StorageBuffer
+%input_var = OpVariable %ptr_input_struct Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid_gep = OpAccessChain %ptr_input_int3 %input_var %int_1
+%gid = OpLoad %int3 %gid_gep
+%gid_x = OpCompositeExtract %int %gid 0
+%gid_y = OpCompositeExtract %int %gid 1
+%lid_gep = OpAccessChain %ptr_input_int3 %input_var %int_0
+%lid = OpLoad %int3 %lid_gep
+%lid_x = OpCompositeExtract %int %lid 0
+%lid_y = OpCompositeExtract %int %lid 1
+%array_gep_0 = OpAccessChain %ptr_array_4 %wg_var %int_0
+%array_gep = OpAccessChain %ptr_array_4 %wg_var %lid_x
+%lid_y_is_1 = OpIEqual %bool %lid_y %int_1
+OpSelectionMerge %loop None
+OpBranchConditional %lid_y_is_1 %then %loop
+
+%then = OpLabel
+; Compute results for outer array
+%large_not_equal = OpPtrNotEqual %bool %array_gep %array_gep_0
+%large_not_equal_gep = OpAccessChain %ptr_int %not_equal_var %int_0 %gid_x %int_16
+%large_not_equal_int = OpSelect %int %large_not_equal %int_1 %int_0
+OpStore %large_not_equal_gep %large_not_equal_int
+;
+OpBranch %loop
+
+%loop = OpLabel
+%i = OpPhi %int %int_0 %entry %int_0 %then %inc_i %loop
+%inc_i = OpIAdd %int %i %int_1
+%i_cmp = OpIEqual %bool %inc_i %int_4
+%lid_offset = OpIMul %int %lid_y %int_4
+%out_gep_index = OpIAdd %int %i %lid_offset
+; Compute results for inner array
+%ref_gep = OpAccessChain %ptr_wg_int %array_gep %lid_y
+%cmp_gep = OpAccessChain %ptr_wg_int %array_gep %i
+%not_equal = OpPtrNotEqual %bool %ref_gep %cmp_gep
+%not_equal_int = OpSelect %int %not_equal %int_1 %int_0
+%not_equal_gep = OpAccessChain %ptr_int %not_equal_var %int_0 %gid_x %out_gep_index
+OpStore %not_equal_gep %not_equal_int
+;
+OpLoopMerge %exit %loop None
+OpBranchConditional %i_cmp %exit %loop
+
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+
+
+[test]
+# 16 x 4 x 2 = 128 work items
+# 4 x 4 = 16 bytes per invocation
+# 2048 bytes from looping
+# 16 x 2 = 32 coarse results (1 per lid)
+# 128 bytes
+# 2176 total bytes
+ssbo 0:0 2176
+
+compute entrypoint main
+compute 2 1 1
+
+#not equal var
+probe ssbo int 0:0 0 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0
+probe ssbo int 0:0 68 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 136 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 204 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 272 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 340 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 408 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 476 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 544 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 612 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 680 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 748 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 816 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 884 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 952 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1020 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1088 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0
+probe ssbo int 0:0 1156 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1224 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1292 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1360 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1428 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1496 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1564 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1632 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1700 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1768 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1836 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1904 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 1972 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 2040 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+probe ssbo int 0:0 2108 == 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1
+
--- /dev/null
+[require]
+
+[compute shader spirv]
+; OpSelect among scalars. This is in SPIR-V 1.0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "data_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_int ArrayStride 4
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+ OpDecorate %_runtimearr_int_0 ArrayStride 4
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_runtimearr_int = OpTypeRuntimeArray %int
+%output_buffer = OpTypeStruct %_runtimearr_int
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_0 = OpConstant %int 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %uint_2 = OpConstant %uint 2
+%_ptr_Input_uint = OpTypePointer Input %uint
+%_runtimearr_int_0 = OpTypeRuntimeArray %int
+%input_buffer = OpTypeStruct %_runtimearr_int_0
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+ %int_1 = OpConstant %int 1
+ %int_2 = OpConstant %int 2
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %18 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %19 = OpLoad %uint %18
+ %24 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %25 = OpLoad %uint %24
+ %27 = OpAccessChain %_ptr_StorageBuffer_int %__0 %int_0 %25
+ %28 = OpLoad %int %27
+ %30 = OpIEqual %bool %28 %int_0
+ %33 = OpSelect %int %30 %int_1 %int_2
+ %34 = OpAccessChain %_ptr_StorageBuffer_int %_ %int_0 %19
+ OpStore %34 %33
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:0 8
+ssbo 0:0 subdata int 0 0 1
+ssbo 0:1 8
+ssbo 0:1 subdata int 0 -1 -1
+
+compute entrypoint main
+compute 1 1 2
+
+probe ssbo int 0:1 0 == 1 2
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Test OpSelect with a scalar condition and composite result type.
+; Generated from the following GLSL with minor modification.
+;
+;#version 430
+;
+;struct S {int a; int b; int c;};
+;
+;layout(std430, binding = 0) buffer input_buffer
+;{
+; S data_SSBO[];
+;};
+;
+;layout(std430, binding = 1) buffer output_buffer
+;{
+; S out_SSBO[];
+;};
+;
+;void main() {
+; S one = { 1, 1, 1 };
+; S two = { 2, 2, 2 };
+;
+; out_SSBO[gl_GlobalInvocationID.z] = (data_SSBO[gl_GlobalInvocationID.z].a == 0 ? one : two);
+;}
+;
+; Applying the no signed wrap decoration
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %S "S"
+ OpMemberName %S 0 "a"
+ OpMemberName %S 1 "b"
+ OpMemberName %S 2 "c"
+ OpName %one "one"
+ OpName %two "two"
+ OpName %S_0 "S"
+ OpMemberName %S_0 0 "a"
+ OpMemberName %S_0 1 "b"
+ OpMemberName %S_0 2 "c"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "data_SSBO"
+ OpName %__0 ""
+ OpMemberDecorate %S_0 0 Offset 0
+ OpMemberDecorate %S_0 1 Offset 4
+ OpMemberDecorate %S_0 2 Offset 8
+ OpDecorate %_runtimearr_S_0 ArrayStride 12
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+ OpDecorate %_runtimearr_S_0_0 ArrayStride 12
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %S = OpTypeStruct %int %int %int
+%_ptr_Function_S = OpTypePointer Function %S
+ %int_1 = OpConstant %int 1
+ %11 = OpConstantComposite %S %int_1 %int_1 %int_1
+ %int_2 = OpConstant %int 2
+ %14 = OpConstantComposite %S %int_2 %int_2 %int_2
+ %S_0 = OpTypeStruct %int %int %int
+%_runtimearr_S_0 = OpTypeRuntimeArray %S_0
+%output_buffer = OpTypeStruct %_runtimearr_S_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %int_0 = OpConstant %int 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %uint_2 = OpConstant %uint 2
+%_ptr_Input_uint = OpTypePointer Input %uint
+%_runtimearr_S_0_0 = OpTypeRuntimeArray %S_0
+%input_buffer = OpTypeStruct %_runtimearr_S_0_0
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %bool = OpTypeBool
+%_ptr_StorageBuffer_S_0 = OpTypePointer StorageBuffer %S_0
+%one = OpConstantComposite %S %int_1 %int_1 %int_1
+%two = OpConstantComposite %S %int_2 %int_2 %int_2
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %27 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %28 = OpLoad %uint %27
+ %36 = OpAccessChain %_ptr_StorageBuffer_int %__0 %int_0 %28 %int_0
+ %37 = OpLoad %int %36
+ %39 = OpIEqual %bool %37 %int_0
+ %sel = OpSelect %S %39 %one %two
+ %48 = OpAccessChain %_ptr_StorageBuffer_S_0 %_ %int_0 %28
+ %49 = OpCompositeExtract %int %sel 0
+ %50 = OpAccessChain %_ptr_StorageBuffer_int %48 %int_0
+ OpStore %50 %49
+ %51 = OpCompositeExtract %int %sel 1
+ %52 = OpAccessChain %_ptr_StorageBuffer_int %48 %int_1
+ OpStore %52 %51
+ %53 = OpCompositeExtract %int %sel 2
+ %54 = OpAccessChain %_ptr_StorageBuffer_int %48 %int_2
+ OpStore %54 %53
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:0 24
+ssbo 0:0 subdata int 0 0 0 0 1 1 1
+ssbo 0:1 8
+ssbo 0:1 subdata int 0 -1 -1 -1 -1 -1 -1
+
+compute entrypoint main
+compute 1 1 2
+
+probe ssbo int 0:1 0 == 1 1 1 2 2 2
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Test OpSelect with a scalar condition and vector result type.
+; Generated from the following GLSL with minor modification.
+;
+; #version 430
+;
+;
+; layout(std430, binding = 0) buffer input_buffer
+; {
+; vec4 data_SSBO[];
+; };
+;
+; layout(std430, binding = 1) buffer output_buffer
+; {
+; vec4 out_SSBO[];
+; };
+;
+; void main() {
+; bool cond = data_SSBO[gl_GlobalInvocationID.z].x == 0.0;
+; vec4 a = {1.0, 3.0, 5.0, 7.0};
+; vec4 b = {2.0, 4.0, 6.0, 8.0};
+; out_SSBO[gl_GlobalInvocationID.z] = (cond ? a : b);
+; }
+
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %_ %__0
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %cond "cond"
+ OpName %input_buffer "input_buffer"
+ OpMemberName %input_buffer 0 "data_SSBO"
+ OpName %_ ""
+ OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+ OpName %a "a"
+ OpName %b "b"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %__0 ""
+ OpDecorate %_runtimearr_v4float ArrayStride 16
+ OpMemberDecorate %input_buffer 0 Offset 0
+ OpDecorate %input_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+ OpDecorate %_runtimearr_v4float_0 ArrayStride 16
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %__0 DescriptorSet 0
+ OpDecorate %__0 Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %bool = OpTypeBool
+%_ptr_Function_bool = OpTypePointer Function %bool
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_runtimearr_v4float = OpTypeRuntimeArray %v4float
+%input_buffer = OpTypeStruct %_runtimearr_v4float
+%_ptr_StorageBuffer_input_buffer = OpTypePointer StorageBuffer %input_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_input_buffer StorageBuffer
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %uint_2 = OpConstant %uint 2
+%_ptr_Input_uint = OpTypePointer Input %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+ %float_0 = OpConstant %float 0
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+ %float_1 = OpConstant %float 1
+ %float_3 = OpConstant %float 3
+ %float_5 = OpConstant %float 5
+ %float_7 = OpConstant %float 7
+ %37 = OpConstantComposite %v4float %float_1 %float_3 %float_5 %float_7
+ %float_2 = OpConstant %float 2
+ %float_4 = OpConstant %float 4
+ %float_6 = OpConstant %float 6
+ %float_8 = OpConstant %float 8
+ %43 = OpConstantComposite %v4float %float_2 %float_4 %float_6 %float_8
+%_runtimearr_v4float_0 = OpTypeRuntimeArray %v4float
+%output_buffer = OpTypeStruct %_runtimearr_v4float_0
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %__0 = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %v4bool = OpTypeVector %bool 4
+%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %cond = OpVariable %_ptr_Function_bool Function
+ %a = OpVariable %_ptr_Function_v4float Function
+ %b = OpVariable %_ptr_Function_v4float Function
+ %23 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %24 = OpLoad %uint %23
+ %27 = OpAccessChain %_ptr_StorageBuffer_float %_ %int_0 %24 %uint_0
+ %28 = OpLoad %float %27
+ %30 = OpFOrdEqual %bool %28 %float_0
+ OpStore %cond %30
+ OpStore %a %37
+ OpStore %b %43
+ %48 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_2
+ %49 = OpLoad %uint %48
+ %50 = OpLoad %bool %cond
+ %51 = OpLoad %v4float %a
+ %52 = OpLoad %v4float %b
+ %55 = OpSelect %v4float %50 %51 %52
+ %57 = OpAccessChain %_ptr_StorageBuffer_v4float %__0 %int_0 %49
+ OpStore %57 %55
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:0 24
+ssbo 0:0 subdata float 0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
+ssbo 0:1 8
+ssbo 0:1 subdata float 0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0
+
+compute entrypoint main
+compute 1 1 2
+
+probe ssbo float 0:1 0 == 1.0 3.0 5.0 7.0 2.0 4.0 6.0 8.0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp zero extend 16-bit 16 value to 32-bit.
+ OpCapability Shader
+ OpCapability Int16
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint16 = OpTypeInt 16 0
+ %uint = OpTypeInt 32 0
+%output_buffer = OpTypeStruct %uint
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %uint
+%spec_const = OpSpecConstant %uint16 16
+%op_spec_const = OpSpecConstantOp %uint UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_int %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 8
+ssbo 0:1 subdata uint 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 16 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp zero extend 32-bit 16 value to 64-bit.
+ OpCapability Shader
+ OpCapability Int64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint64 = OpTypeInt 64 0
+%output_buffer = OpTypeStruct %uint64
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int64 = OpTypePointer StorageBuffer %uint64
+%spec_const = OpSpecConstant %uint 16
+%op_spec_const = OpSpecConstantOp %uint64 UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_int64 %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 subdata uint64_t 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint64_t 0:1 0 == 16 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp zero extend 32-bit 0xF0000000 value (251,658,240) to 64-bit.
+ OpCapability Shader
+ OpCapability Int64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint64 = OpTypeInt 64 0
+%output_buffer = OpTypeStruct %uint64
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint64 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %uint64
+%spec_const = OpSpecConstant %uint 251658240
+%op_spec_const = OpSpecConstantOp %uint64 UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_int %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 subdata uint64_t 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint64_t 0:1 0 == 251658240 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp zero extend 16-bit 0xF000 value (61,440) to 32-bit.
+ OpCapability Shader
+ OpCapability Int16
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint16 = OpTypeInt 16 0
+ %uint = OpTypeInt 32 0
+%output_buffer = OpTypeStruct %uint
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %uint
+%spec_const = OpSpecConstant %uint16 61440
+%op_spec_const = OpSpecConstantOp %uint UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_int %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 8
+ssbo 0:1 subdata uint 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 61440 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp truncate 32-bit 16 value to 16-bit.
+ OpCapability Shader
+ OpCapability Int16
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint16 = OpTypeInt 16 0
+ %uint = OpTypeInt 32 0
+%output_buffer = OpTypeStruct %uint16
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint16 = OpTypePointer StorageBuffer %uint16
+%spec_const = OpSpecConstant %uint 16
+%op_spec_const = OpSpecConstantOp %uint16 UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_uint16 %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 4
+ssbo 0:1 subdata uint8_t 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint8_t 0:1 0 == 16 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp truncate 64-bit 16 value to 32-bit.
+ OpCapability Shader
+ OpCapability Int64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint64 = OpTypeInt 64 0
+%output_buffer = OpTypeStruct %uint
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint64 0
+%_ptr_StorageBuffer_uint16 = OpTypePointer StorageBuffer %uint
+%spec_const = OpSpecConstant %uint64 16
+%op_spec_const = OpSpecConstantOp %uint UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_uint16 %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 subdata uint 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 16 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp truncate 32-bit 983,041 value to 16-bit.
+ OpCapability Shader
+ OpCapability Int16
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint16 = OpTypeInt 16 0
+ %uint = OpTypeInt 32 0
+%output_buffer = OpTypeStruct %uint16
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint16 = OpTypePointer StorageBuffer %uint16
+%spec_const = OpSpecConstant %uint 983041
+%op_spec_const = OpSpecConstantOp %uint16 UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_uint16 %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 4
+ssbo 0:1 subdata uint8_t 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint8_t 0:1 0 == 1 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; SpecConstantOp zero extend signed 16-bit 0xF000 value (-4,096) to 32-bit.
+; A value that is produced as a signed value is passed to UConvert, but it
+; must still be interpreted as an unsigned value.
+ OpCapability Shader
+ OpCapability Int16
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %_
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource GLSL 430
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %output_buffer "output_buffer"
+ OpMemberName %output_buffer 0 "out_SSBO"
+ OpName %_ ""
+ OpMemberDecorate %output_buffer 0 Offset 0
+ OpDecorate %output_buffer Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int16 = OpTypeInt 16 1
+ %uint = OpTypeInt 32 0
+%output_buffer = OpTypeStruct %uint
+%_ptr_StorageBuffer_output_buffer = OpTypePointer StorageBuffer %output_buffer
+ %_ = OpVariable %_ptr_StorageBuffer_output_buffer StorageBuffer
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %uint
+%spec_const = OpSpecConstant %int16 -4096
+%op_spec_const = OpSpecConstantOp %uint UConvert %spec_const
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %34 = OpAccessChain %_ptr_StorageBuffer_int %_ %uint_0
+ OpStore %34 %op_spec_const
+ OpReturn
+ OpFunctionEnd
+[test]
+ssbo 0:1 8
+ssbo 0:1 subdata uint 0 0 0
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo uint 0:1 0 == 61440 0
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %gid_var %in_var %out_var
+OpExecutionMode %main LocalSize 8 1 1
+
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorateId %then_ld UniformId %workgroup
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_2 = OpConstant %int 2
+%workgroup = OpConstant %int 2
+%int3 = OpTypeVector %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%struct = OpTypeStruct %int_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+
+%ptr_input_int3 = OpTypePointer Input %int3
+%gid_var = OpVariable %ptr_input_int3 Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid = OpLoad %int3 %gid_var
+%gid_x = OpCompositeExtract %int %gid 0
+%in_gep = OpAccessChain %ptr_ssbo_int %in_var %int_0 %gid_x
+%mod = OpUMod %int %gid_x %int_2
+%eq = OpIEqual %bool %mod %int_0
+OpSelectionMerge %merge None
+OpBranchConditional %eq %then %else
+
+%then = OpLabel
+%then_ld = OpLoad %int %in_gep
+OpBranch %merge
+
+%else = OpLabel
+%else_ld = OpLoad %int %in_gep
+OpBranch %merge
+
+%merge = OpLabel
+%phi = OpPhi %int %then_ld %then %else_ld %else
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %out_gep %phi
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9
+ssbo 0:1 64
+compute entrypoint main
+compute 2 1 1
+
+probe ssbo uint 0:1 0 == 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %gid_var %in_var %out_var
+OpExecutionMode %main LocalSize 8 1 1
+
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorateId %cmp UniformId %subgroup
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_10 = OpConstant %int 10
+%int_100 = OpConstant %int 100
+%int_50 = OpConstant %int 50
+%subgroup = OpConstant %int 3
+%int3 = OpTypeVector %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%struct = OpTypeStruct %int_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+
+%ptr_input_int3 = OpTypePointer Input %int3
+%gid_var = OpVariable %ptr_input_int3 Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid = OpLoad %int3 %gid_var
+%gid_x = OpCompositeExtract %int %gid 0
+%in_gep = OpAccessChain %ptr_ssbo_int %in_var %int_0 %gid_x
+%ld = OpLoad %int %in_gep
+%cmp = OpULessThan %bool %ld %int_10
+OpSelectionMerge %merge None
+OpBranchConditional %cmp %then %else
+
+%then = OpLabel
+%then_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %then_gep %int_100
+OpBranch %merge
+
+%else = OpLabel
+%else_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %else_gep %int_50
+OpBranch %merge
+
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17
+ssbo 0:1 64
+
+compute entrypoint main
+compute 2 1 1
+
+probe ssbo uint 0:1 0 == 100 100 100 100 100 100 100 100 50 50 50 50 50 50 50 50
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %gid_var %in_var %out_var
+OpExecutionMode %main LocalSize 8 1 1
+
+OpDecorate %lid_var BuiltIn LocalInvocationId
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorateId %in_ld UniformId %subgroup
+
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%subgroup = OpConstant %int 3
+%int3 = OpTypeVector %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%struct = OpTypeStruct %int_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+
+%ptr_input_int3 = OpTypePointer Input %int3
+%lid_var = OpVariable %ptr_input_int3 Input
+%gid_var = OpVariable %ptr_input_int3 Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid = OpLoad %int3 %gid_var
+%gid_x = OpCompositeExtract %int %gid 0
+%in_gep = OpAccessChain %ptr_ssbo_int %in_var %int_0 %gid_x
+%in_ld = OpLoad %int %in_gep
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %out_gep %in_ld
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 1 1 1 1 1 1 1 1
+ssbo 0:0 subdata uint 32 2 2 2 2 2 2 2 2
+ssbo 0:0 subdata uint 64 3 3 3 3 3 3 3 3
+ssbo 0:0 subdata uint 96 4 4 4 4 4 4 4 4
+ssbo 0:1 128
+
+compute entrypoint main
+compute 4 1 1
+
+probe ssbo uint 0:1 0 == 1 1 1 1 1 1 1 1
+probe ssbo uint 0:1 32 == 2 2 2 2 2 2 2 2
+probe ssbo uint 0:1 64 == 3 3 3 3 3 3 3 3
+probe ssbo uint 0:1 96 == 4 4 4 4 4 4 4 4
+
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %gid_var %in_var %out_var
+OpExecutionMode %main LocalSize 8 1 1
+
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorateId %cmp UniformId %workgroup
+
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_10 = OpConstant %int 10
+%int_100 = OpConstant %int 100
+%int_50 = OpConstant %int 50
+%workgroup = OpConstant %int 2
+%int3 = OpTypeVector %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%struct = OpTypeStruct %int_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+
+%ptr_input_int3 = OpTypePointer Input %int3
+%gid_var = OpVariable %ptr_input_int3 Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid = OpLoad %int3 %gid_var
+%gid_x = OpCompositeExtract %int %gid 0
+%in_gep = OpAccessChain %ptr_ssbo_int %in_var %int_0 %gid_x
+%ld = OpLoad %int %in_gep
+%cmp = OpULessThan %bool %ld %int_10
+OpSelectionMerge %merge None
+OpBranchConditional %cmp %then %else
+
+%then = OpLabel
+%then_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %then_gep %int_100
+OpBranch %merge
+
+%else = OpLabel
+%else_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %else_gep %int_50
+OpBranch %merge
+
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17
+ssbo 0:1 64
+
+compute entrypoint main
+compute 2 1 1
+
+probe ssbo uint 0:1 0 == 100 100 100 100 100 100 100 100 50 50 50 50 50 50 50 50
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+VK_KHR_storage_buffer_storage_class
+
+[compute shader spirv]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %gid_var %in_var %out_var
+OpExecutionMode %main LocalSize 8 1 1
+
+OpDecorate %lid_var BuiltIn LocalInvocationId
+OpDecorate %gid_var BuiltIn GlobalInvocationId
+
+OpDecorate %int_rta ArrayStride 4
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+
+OpDecorateId %in_ld UniformId %workgroup
+
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%workgroup = OpConstant %int 2
+%int3 = OpTypeVector %int 3
+
+%int_rta = OpTypeRuntimeArray %int
+%struct = OpTypeStruct %int_rta
+%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
+%in_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%out_var = OpVariable %ptr_ssbo_struct StorageBuffer
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+
+%ptr_input_int3 = OpTypePointer Input %int3
+%lid_var = OpVariable %ptr_input_int3 Input
+%gid_var = OpVariable %ptr_input_int3 Input
+
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+%gid = OpLoad %int3 %gid_var
+%gid_x = OpCompositeExtract %int %gid 0
+%in_gep = OpAccessChain %ptr_ssbo_int %in_var %int_0 %gid_x
+%in_ld = OpLoad %int %in_gep
+%out_gep = OpAccessChain %ptr_ssbo_int %out_var %int_0 %gid_x
+OpStore %out_gep %in_ld
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 subdata uint 0 1 1 1 1 1 1 1 1
+ssbo 0:0 subdata uint 32 2 2 2 2 2 2 2 2
+ssbo 0:0 subdata uint 64 3 3 3 3 3 3 3 3
+ssbo 0:0 subdata uint 96 4 4 4 4 4 4 4 4
+ssbo 0:1 128
+
+compute entrypoint main
+compute 4 1 1
+
+probe ssbo uint 0:1 0 == 1 1 1 1 1 1 1 1
+probe ssbo uint 0:1 32 == 2 2 2 2 2 2 2 2
+probe ssbo uint 0:1 64 == 3 3 3 3 3 3 3 3
+probe ssbo uint 0:1 96 == 4 4 4 4 4 4 4 4
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Applying the no signed wrap decoration
+
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+OpDecorate %struct1 Block
+OpMemberDecorate %struct1 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+OpDecorate %out_int NoSignedWrap
+%void = OpTypeVoid
+%int = OpTypeInt 32 1
+%int_10 = OpConstant %int 10
+
+%struct1 = OpTypeStruct %int
+%ptr_struct1 = OpTypePointer StorageBuffer %struct1
+
+%in_var = OpVariable %ptr_struct1 StorageBuffer
+%out_var = OpVariable %ptr_struct1 StorageBuffer
+
+%func_ty = OpTypeFunction %void
+%main = OpFunction %void None %func_ty
+%1 = OpLabel
+%in_struct = OpLoad %struct1 %in_var
+%in_int = OpCompositeExtract %int %in_struct 0
+%out_int = OpIAdd %int %in_int %int_10
+%out_struct = OpCompositeConstruct %struct1 %out_int
+OpStore %out_var %out_struct
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 4
+ssbo 0:0 subdata int 0 0
+ssbo 0:1 4
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 10
--- /dev/null
+[require]
+VK_KHR_spirv_1_4
+
+[compute shader spirv]
+; Applying the no signed wrap decoration
+
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %in_var %out_var
+OpExecutionMode %main LocalSize 1 1 1
+OpDecorate %struct1 Block
+OpMemberDecorate %struct1 0 Offset 0
+OpDecorate %in_var DescriptorSet 0
+OpDecorate %in_var Binding 0
+OpDecorate %out_var DescriptorSet 0
+OpDecorate %out_var Binding 1
+OpDecorate %out_int NoUnsignedWrap
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_10 = OpConstant %int 10
+
+%struct1 = OpTypeStruct %int
+%ptr_struct1 = OpTypePointer StorageBuffer %struct1
+
+%in_var = OpVariable %ptr_struct1 StorageBuffer
+%out_var = OpVariable %ptr_struct1 StorageBuffer
+
+%func_ty = OpTypeFunction %void
+%main = OpFunction %void None %func_ty
+%1 = OpLabel
+%in_struct = OpLoad %struct1 %in_var
+%in_int = OpCompositeExtract %int %in_struct 0
+%out_int = OpIAdd %int %in_int %int_10
+%out_struct = OpCompositeConstruct %struct1 %out_int
+OpStore %out_var %out_struct
+OpReturn
+OpFunctionEnd
+
+[test]
+ssbo 0:0 4
+ssbo 0:0 subdata int 0 0
+ssbo 0:1 4
+
+compute entrypoint main
+compute 1 1 1
+
+probe ssbo int 0:1 0 == 10
void AmberTestCase::setSpirVAsmBuildOptions(const vk::SpirVAsmBuildOptions& asm_options)
{
- m_asm_options = asm_options;
+ m_asm_options = asm_options;
}
void AmberTestCase::addRequirement(const std::string& requirement)
*//*--------------------------------------------------------------------*/
#include <string>
+#include <vector>
#include <amber/amber.h>
#include "tcuDefs.hpp"
struct Case
{
- Case(const char* b, const char* d) : basename(b), description(d) { }
+ Case(const char* b, const char* d) : basename(b), description(d), requirements() { }
+ Case(const char* b, const char* d, const std::vector<std::string>& e) : basename(b), description(d), requirements(e) { }
const char *basename;
const char *description;
+ // Additional Vulkan requirements, if any.
+ std::vector<std::string> requirements;
};
struct CaseGroup
{
CaseGroup(const char* the_data_dir, const char* the_subdir) : data_dir(the_data_dir), subdir(the_subdir) { }
- void add(const char* basename, const char* description) { cases.push_back(Case(basename, description)); }
+ void add(const char* basename, const char* description)
+ {
+ cases.push_back(Case(basename, description));
+ }
+ void add(const char* basename, const char* description, const std::vector<std::string>& requirements)
+ {
+ cases.push_back(Case(basename, description, requirements));
+ }
const char* data_dir;
const char* subdir;
// extensions folded into SPIR-V 1.4 or earlier, and which don't require extra capabilities
// to be enabled by Vulkan. Other examples are functionality in SPV_GOOGLE_decorate_string,
// SPV_GOOGLE_hlsl_functionality1, and SPV_KHR_no_integer_wrap_decoration.
+ const std::vector<std::string>& reqmts = cases[i].requirements;
+ for (size_t r = 0; r < reqmts.size() ; ++r)
+ {
+ testCase->addRequirement(reqmts[r]);
+ }
testCase->setSpirVAsmBuildOptions(asm_options);
tests->addChild(testCase);
// Location of the Amber script files under the data/vulkan/amber source tree.
const char* data_dir = "spirv_assembly/instruction/spirv1p4";
+ // Set up features used for various tests.
+ std::vector<std::string> Geom;
+ Geom.push_back("Features.geometryShader");
+
+ std::vector<std::string> Tess;
+ Tess.push_back("Features.tessellationShader");
+
+ std::vector<std::string> Varptr_ssbo;
+ Varptr_ssbo.push_back("VariablePointerFeatures.variablePointersStorageBuffer");
+
+ std::vector<std::string> Varptr_full = Varptr_ssbo;
+ Varptr_full.push_back("VariablePointerFeatures.variablePointers");
+
+ std::vector<std::string> Int16;
+ Int16.push_back("Features.shaderInt16");
+
+ std::vector<std::string> Int64;
+ Int64.push_back("Features.shaderInt64");
+
+ // Define test groups
+
CaseGroup group(data_dir, "opcopylogical");
group.add("different_matrix_layout","different matrix layout");
group.add("different_matrix_strides","different matrix strides");
group.add("ubo_to_ssbo","ubo_to_ssbo");
spirv1p4Tests->addChild(createTestGroup(testCtx, "opcopylogical", "OpCopyLogical", addTestsForAmberFiles, group));
+ group = CaseGroup(data_dir, "opptrdiff");
+ group.add("ssbo_comparisons_diff", "pointer diff within an SSBO", Varptr_ssbo);
+ group.add("variable_pointers_vars_ssbo_2_diff", "pointer diff in SSBO with full VariablePointers", Varptr_full);
+ group.add("variable_pointers_vars_ssbo_diff", "pointer diff in SSBO, stored in private var", Varptr_ssbo);
+ group.add("variable_pointers_vars_wg_diff", "pointer diff in workgroup storage, stored in private var", Varptr_full);
+ group.add("wg_comparisons_diff", "pointer diff in workgroup storage", Varptr_full);
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "opptrdiff", "OpPtrDiff", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "opptrequal");
+ group.add("null_comparisons_ssbo_equal", "ptr equal null in SSBO", Varptr_ssbo);
+ group.add("null_comparisons_wg_equal", "ptr equal null in Workgrop", Varptr_full);
+ group.add("ssbo_comparisons_equal", "ptr equal in SSBO", Varptr_ssbo);
+ group.add("variable_pointers_ssbo_2_equal", "ptr equal in SSBO, store pointers in Function var", Varptr_full);
+ group.add("variable_pointers_ssbo_equal", "ptr equal in SSBO", Varptr_ssbo);
+ group.add("variable_pointers_vars_ssbo_equal", "ptr equal in SSBO, store pointers in Private var ", Varptr_ssbo);
+ group.add("variable_pointers_vars_wg_equal", "ptr equal in Workgrop, store pointers in Private var", Varptr_full);
+ group.add("variable_pointers_wg_equal", "ptr equal in Workgrop", Varptr_full);
+ group.add("wg_comparisons_equal", "ptr equal in Workgrop", Varptr_full);
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "opptrequal", "OpPtrEqual", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "opptrnotequal");
+ group.add("null_comparisons_ssbo_not_equal", "ptr not equal null SSBO", Varptr_ssbo);
+ group.add("null_comparisons_wg_not_equal", "ptr not equal null SSBO", Varptr_full);
+ group.add("ssbo_comparisons_not_equal", "ptr not equal SSBO", Varptr_ssbo);
+ group.add("variable_pointers_ssbo_2_not_equal", "ptr not equal SSBO, store pointer in Function var", Varptr_full);
+ group.add("variable_pointers_ssbo_not_equal", "ptr not equal SSBO, pointer from function return", Varptr_ssbo);
+ group.add("variable_pointers_vars_ssbo_not_equal", "ptr not equal SSBO, store pointer in Private var", Varptr_ssbo);
+ group.add("variable_pointers_vars_wg_not_equal", "ptr not equal Workgroup, store pointer in Private var", Varptr_ssbo);
+ group.add("variable_pointers_wg_not_equal", "ptr not equal Workgroup", Varptr_full);
+ group.add("wg_comparisons_not_equal", "ptr not equal Workgroup", Varptr_full);
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "opptrnotequal", "OpPtrNotEqual", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "opcopymemory");
+ group.add("different_alignments", "different alignments");
+ group.add("no_source_access_operands", "no source access operands");
+ group.add("no_target_access_operands", "no target access operands");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "opcopymemory", "OpCopyMemory 2 memory access operands", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "uniformid");
+ group.add("partially_active_uniform_id","workgroup uniform load result at consumption, in nonuniform control flow");
+ group.add("subgroup_cfg_uniform_id","subgroup uniform compare result inside control flow"); // Assumes subgroup size <= LocalSize of 8
+ group.add("subgroup_uniform","subgroup uniform load result"); // Assumes subgroup size <= LocalSize 8
+ group.add("workgroup_cfg_uniform_id","workgroup uniform compare result");
+ group.add("workgroup_uniform","workgroup uniform load result");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "uniformid", "UniformId decoration", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "nonwritable");
+ group.add("function_2_nonwritable", "NonWritable decorates Function variables");
+ group.add("function_nonwritable", "NonWritable decorates 2 Function variables");
+ group.add("private_2_nonwritable", "NonWritable decorates Private variables");
+ group.add("private_nonwritable", "NonWritable decorates 2 Private variables");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "nonwritable", "NonWritable decoration", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "entrypoint");
+ group.add("comp_pc_entry_point", "push constant on compute shader entry point");
+ group.add("comp_ssbo_entry_point", "SSBO on compute shader entry point");
+ group.add("comp_ubo_entry_point", "UBO on compute shader entry point");
+ group.add("comp_workgroup_entry_point", "Workgroup var on compute shader entry point");
+ group.add("frag_pc_entry_point", "push constant on fragment shader entry point");
+ group.add("frag_ssbo_entry_point", "SSBO on fragment shader entry point");
+ group.add("frag_ubo_entry_point", "UBO on fragment shader entry point");
+ group.add("geom_pc_entry_point", "push constant on geometry shader entry point", Geom);
+ group.add("geom_ssbo_entry_point", "SSBO on geometry shader entry point", Geom);
+ group.add("geom_ubo_entry_point", "UBO on geometry shader entry point", Geom);
+ group.add("tess_con_pc_entry_point", "push constant on tess control shader entry point", Tess);
+ group.add("tess_con_ssbo_entry_point", "SSBO on tess control shader entry point", Tess);
+ group.add("tess_con_ubo_entry_point", "UBO on tess control shader entry point", Tess);
+ group.add("tess_eval_pc_entry_point", "push constant on tess eval shader entry point", Tess);
+ group.add("tess_eval_ssbo_entry_point", "SSBO on tess eval shader entry point", Tess);
+ group.add("tess_eval_ubo_entry_point", "UBO on tess eval shader entry point", Tess);
+ group.add("vert_pc_entry_point", "push constant on vertex shader entry point");
+ group.add("vert_ssbo_entry_point", "SSBO on vertex shader entry point");
+ group.add("vert_ubo_entry_point", "UBO on vertex shader entry point");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "entrypoint", "EntryPoint lists all module-scope variables", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "hlsl_functionality1");
+ group.add("counter_buffer", "CounterBuffer decoration");
+ group.add("decorate_string", "OpDecorateString");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "hlsl_functionality1", "Features in SPV_GOOGLE_hlsl_functionality1 in SPIR-V 1.4", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "loop_control");
+ group.add("iteration_multiple", "Loop control IterationMultiple");
+ group.add("max_iterations", "Loop control IterationMultiple");
+ group.add("min_iterations", "Loop control MinIterations");
+ group.add("partial_count", "Loop control PartialCount");
+ group.add("peel_count", "Loop control PeelCount");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "loop_control", "SPIR-V 1.4 loop controls", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "opselect");
+ group.add("scalar_select", "OpSelect scalars, verify SPIR-V 1.0");
+ group.add("struct_select", "OpSelect structs, new in SPIR-V 1.4");
+ group.add("vector_select", "OpSelect vector with scalar selector, new in SPIR-V 1.4");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "opselect", "SPIR-V 1.4 OpSelect more cases", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "uconvert");
+ group.add("spec_const_opt_extend_16_64_bit","uconvert small to int64", Int64);
+ group.add("spec_const_opt_extend_16","uconvert from int16", Int16);
+ group.add("spec_const_opt_extend_251658240_64_bits","uconvert large to int64", Int64);
+ group.add("spec_const_opt_extend_61440", "uconvert large from int16", Int16);
+ group.add("spec_const_opt_truncate_16_64_bit", "uconvert from int64", Int64);
+ group.add("spec_const_opt_truncate_16", "uconvert small to int16", Int16);
+ group.add("spec_const_opt_truncate_983040", "uconvert large to int16", Int16);
+ group.add("spec_const_opt_zero_extend_n4096", "uconvert negative from int16", Int16);
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "uconvert", "SPIR-V 1.4 UConvert in OpSpecConstantOp", addTestsForAmberFiles, group));
+
+ group = CaseGroup(data_dir, "wrap");
+ group.add("no_signed_wrap", "Accept NoSignedWrap decoration");
+ group.add("no_unsigned_wrap", "Accept NoUnsignedWrap decoration");
+ spirv1p4Tests->addChild(createTestGroup(testCtx, "wrap", "SPIR-V 1.4 integer wrap decorations", addTestsForAmberFiles, group));
+
return spirv1p4Tests.release();
}
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.two_arrays_different_stride_1
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.two_arrays_different_stride_2
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.ubo_to_ssbo
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.ssbo_comparisons_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_ssbo_2_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_ssbo_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_wg_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.wg_comparisons_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.null_comparisons_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.null_comparisons_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.ssbo_comparisons_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_ssbo_2_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_vars_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_vars_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.wg_comparisons_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.null_comparisons_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.null_comparisons_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.ssbo_comparisons_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_ssbo_2_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_vars_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_vars_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.wg_comparisons_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.different_alignments
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.no_source_access_operands
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.no_target_access_operands
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.partially_active_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.subgroup_cfg_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.subgroup_uniform
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.workgroup_cfg_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.workgroup_uniform
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.function_2_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.function_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.private_2_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.private_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_workgroup_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.hlsl_functionality1.counter_buffer
+dEQP-VK.spirv_assembly.instruction.spirv1p4.hlsl_functionality1.decorate_string
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.iteration_multiple
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.max_iterations
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.min_iterations
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.partial_count
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.peel_count
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.scalar_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.struct_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.vector_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_16_64_bit
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_16
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_251658240_64_bits
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_61440
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_16_64_bit
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_16
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_983040
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_zero_extend_n4096
+dEQP-VK.spirv_assembly.instruction.spirv1p4.wrap.no_signed_wrap
+dEQP-VK.spirv_assembly.instruction.spirv1p4.wrap.no_unsigned_wrap
dEQP-VK.spirv_assembly.type.scalar.i8.negate_vert
dEQP-VK.spirv_assembly.type.scalar.i8.negate_tessc
dEQP-VK.spirv_assembly.type.scalar.i8.negate_tesse
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.two_arrays_different_stride_1
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.two_arrays_different_stride_2
dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopylogical.ubo_to_ssbo
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.ssbo_comparisons_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_ssbo_2_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_ssbo_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.variable_pointers_vars_wg_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrdiff.wg_comparisons_diff
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.null_comparisons_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.null_comparisons_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.ssbo_comparisons_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_ssbo_2_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_vars_ssbo_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_vars_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.variable_pointers_wg_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrequal.wg_comparisons_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.null_comparisons_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.null_comparisons_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.ssbo_comparisons_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_ssbo_2_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_vars_ssbo_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_vars_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.variable_pointers_wg_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opptrnotequal.wg_comparisons_not_equal
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.different_alignments
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.no_source_access_operands
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opcopymemory.no_target_access_operands
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.partially_active_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.subgroup_cfg_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.subgroup_uniform
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.workgroup_cfg_uniform_id
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uniformid.workgroup_uniform
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.function_2_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.function_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.private_2_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.nonwritable.private_nonwritable
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.comp_workgroup_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.frag_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.geom_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_con_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.tess_eval_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_pc_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_ssbo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.entrypoint.vert_ubo_entry_point
+dEQP-VK.spirv_assembly.instruction.spirv1p4.hlsl_functionality1.counter_buffer
+dEQP-VK.spirv_assembly.instruction.spirv1p4.hlsl_functionality1.decorate_string
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.iteration_multiple
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.max_iterations
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.min_iterations
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.partial_count
+dEQP-VK.spirv_assembly.instruction.spirv1p4.loop_control.peel_count
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.scalar_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.struct_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.opselect.vector_select
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_16_64_bit
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_16
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_251658240_64_bits
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_extend_61440
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_16_64_bit
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_16
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_truncate_983040
+dEQP-VK.spirv_assembly.instruction.spirv1p4.uconvert.spec_const_opt_zero_extend_n4096
+dEQP-VK.spirv_assembly.instruction.spirv1p4.wrap.no_signed_wrap
+dEQP-VK.spirv_assembly.instruction.spirv1p4.wrap.no_unsigned_wrap
dEQP-VK.spirv_assembly.type.scalar.i8.negate_vert
dEQP-VK.spirv_assembly.type.scalar.i8.negate_tessc
dEQP-VK.spirv_assembly.type.scalar.i8.negate_tesse