Test OpUndef with OpConstantComposite and OpSpecConstantComposite

This commit tests OpUndef can be used to create partially defined
constant composite structures by using OpUndev values when constructing
other values with OpConstantComposite and OpSpecConstantComposite.

New tests:
dEQP-VK.spirv_assembly.instruction.compute.opundef.undefined_*

Components: Vulkan
VK-GL-CTS issue: 2243

Change-Id: I518dd029b4e00a5d5d33603d4776ce643c2adba8
diff --git a/android/cts/master/vk-master-2020-03-01.txt b/android/cts/master/vk-master-2020-03-01.txt
index 24c0f87..c6b9918 100644
--- a/android/cts/master/vk-master-2020-03-01.txt
+++ b/android/cts/master/vk-master-2020-03-01.txt
@@ -86410,6 +86410,8 @@
 dEQP-VK.spirv_assembly.instruction.compute.opspecconstantop.shiftrightlogical_s_i8
 dEQP-VK.spirv_assembly.instruction.compute.opspecconstantop.shiftrightarithmetic_s_i8
 dEQP-VK.spirv_assembly.instruction.compute.opspecconstantop.shiftleftlogical_s_i8
+dEQP-VK.spirv_assembly.instruction.compute.opundef.undefined_constant_composite
+dEQP-VK.spirv_assembly.instruction.compute.opundef.undefined_spec_constant_composite
 dEQP-VK.spirv_assembly.instruction.compute.opunreachable.unreachable-switch-merge-in-loop
 dEQP-VK.spirv_assembly.instruction.compute.uconvert.int8_to_uint16
 dEQP-VK.spirv_assembly.instruction.compute.uconvert.int8_to_uint32
diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt
index a4b41bd..1ea988b 100644
--- a/android/cts/master/vk-master.txt
+++ b/android/cts/master/vk-master.txt
Binary files differ
diff --git a/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/undef/undefined_constant_composite.amber b/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/undef/undefined_constant_composite.amber
new file mode 100644
index 0000000..b2e76b1
--- /dev/null
+++ b/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/undef/undefined_constant_composite.amber
@@ -0,0 +1,135 @@
+#!amber
+
+# Copyright 2020 Valve Corporation.
+# Copyright 2020 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+SHADER compute comp SPIRV-ASM
+;
+; The shader below is based on the following GLSL shader:
+;
+;     #version 450
+;
+;     struct Pair {
+;         int first;
+;         int second;
+;     };
+;
+;     const Pair constant_pair = { 100, 200 };
+;
+;     layout(set=0, binding=0, std430) buffer InputBlock {
+;         int array[10];
+;     } inputValues;
+;
+;     layout(set=0, binding=1, std430) buffer OutputBlock {
+;         int array[10];
+;     } outputValues;
+;
+;     int add_second (int value, Pair pair) {
+;         return value + pair.second;
+;     }
+;
+;     void main() {
+;         uint idx = gl_GlobalInvocationID.x;
+;         outputValues.array[idx] = add_second(inputValues.array[idx], constant_pair);
+;     }
+;
+; However, the first element of constant_pair has been modified to be undefined.
+;
+                            OpCapability Shader
+                  %std450 = OpExtInstImport "GLSL.std.450"
+                            OpMemoryModel Logical GLSL450
+                            OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
+                            OpExecutionMode %main LocalSize 1 1 1
+                            OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+                            OpDecorate %_arr_int_uint_10 ArrayStride 4
+                            OpMemberDecorate %OutputBlock 0 Offset 0
+                            OpDecorate %OutputBlock BufferBlock
+                            OpDecorate %outputValues DescriptorSet 0
+                            OpDecorate %outputValues Binding 1
+                            OpMemberDecorate %InputBlock 0 Offset 0
+                            OpDecorate %InputBlock BufferBlock
+                            OpDecorate %inputValues DescriptorSet 0
+                            OpDecorate %inputValues Binding 0
+                    %void = OpTypeVoid
+               %void_func = OpTypeFunction %void
+                     %int = OpTypeInt 32 1
+                    %uint = OpTypeInt 32 0
+                  %v3uint = OpTypeVector %uint 3
+                   %int_0 = OpConstant %int 0
+                   %int_1 = OpConstant %int 1
+                 %int_200 = OpConstant %int 200
+                  %uint_0 = OpConstant %uint 0
+                 %uint_10 = OpConstant %uint 10
+       %_ptr_Function_int = OpTypePointer Function %int
+                    %Pair = OpTypeStruct %int %int
+      %_ptr_Function_Pair = OpTypePointer Function %Pair
+    %add_second_func_type = OpTypeFunction %int %_ptr_Function_int %_ptr_Function_Pair
+      %_ptr_Function_uint = OpTypePointer Function %uint
+       %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+         %_ptr_Input_uint = OpTypePointer Input %uint
+        %_arr_int_uint_10 = OpTypeArray %int %uint_10
+             %OutputBlock = OpTypeStruct %_arr_int_uint_10
+%_ptr_Uniform_OutputBlock = OpTypePointer Uniform %OutputBlock
+            %outputValues = OpVariable %_ptr_Uniform_OutputBlock Uniform
+              %InputBlock = OpTypeStruct %_arr_int_uint_10
+ %_ptr_Uniform_InputBlock = OpTypePointer Uniform %InputBlock
+             %inputValues = OpVariable %_ptr_Uniform_InputBlock Uniform
+                            ; Replaced %int_100 with an undefined int.
+               %undef_int = OpUndef %int
+                            ; Composed a constant Pair with the undefined int in the first member.
+              %const_Pair = OpConstantComposite %Pair %undef_int %int_200
+        %_ptr_Uniform_int = OpTypePointer Uniform %int
+   %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+                    %main = OpFunction %void None %void_func
+              %main_label = OpLabel
+                 %param_1 = OpVariable %_ptr_Function_int Function
+                 %param_2 = OpVariable %_ptr_Function_Pair Function
+                %gidx_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
+                    %gidx = OpLoad %uint %gidx_ptr
+         %input_value_ptr = OpAccessChain %_ptr_Uniform_int %inputValues %int_0 %gidx
+             %input_value = OpLoad %int %input_value_ptr
+                            OpStore %param_1 %input_value
+                            OpStore %param_2 %const_Pair
+                  %retval = OpFunctionCall %int %add_second %param_1 %param_2
+        %output_value_ptr = OpAccessChain %_ptr_Uniform_int %outputValues %int_0 %gidx
+                            OpStore %output_value_ptr %retval
+                            OpReturn
+                            OpFunctionEnd
+              %add_second = OpFunction %int None %add_second_func_type
+               %value_ptr = OpFunctionParameter %_ptr_Function_int
+                    %pair = OpFunctionParameter %_ptr_Function_Pair
+        %add_second_label = OpLabel
+                   %value = OpLoad %int %value_ptr
+                            ; Access the second struct member, which is defined.
+         %pair_second_ptr = OpAccessChain %_ptr_Function_int %pair %int_1
+             %pair_second = OpLoad %int %pair_second_ptr
+              %add_result = OpIAdd %int %value %pair_second
+                            OpReturnValue %add_result
+                            OpFunctionEnd
+END
+
+BUFFER input_buffer DATA_TYPE int32 SIZE 10 SERIES_FROM 1000 INC_BY 1
+BUFFER output_buffer DATA_TYPE int32 SIZE 10 FILL 0
+BUFFER reference_buffer DATA_TYPE int32 SIZE 10 SERIES_FROM 1200 INC_BY 1
+
+PIPELINE compute compute_pipeline
+	ATTACH comp
+	BIND BUFFER input_buffer AS storage DESCRIPTOR_SET 0 BINDING 0
+	BIND BUFFER output_buffer AS storage DESCRIPTOR_SET 0 BINDING 1
+END
+
+RUN compute_pipeline 10 1 1
+EXPECT output_buffer EQ_BUFFER reference_buffer
diff --git a/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/undef/undefined_spec_constant_composite.amber b/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/undef/undefined_spec_constant_composite.amber
new file mode 100644
index 0000000..5c04910
--- /dev/null
+++ b/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/undef/undefined_spec_constant_composite.amber
@@ -0,0 +1,155 @@
+#!amber
+
+# Copyright 2020 Valve Corporation.
+# Copyright 2020 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+SHADER compute comp SPIRV-ASM
+;
+; The shader below is based on the following GLSL shader:
+;
+;     #version 450
+;
+;     struct Pair {
+;         int first;
+;         int second;
+;     };
+;
+;     const Pair constant_pair = { 100, 200 };
+;
+;     layout (constant_id=0) const int constantFirst = 0;
+;
+;     Pair spec_constant_pair = { constantFirst, 200 };
+;
+;     layout(set=0, binding=0, std430) buffer InputBlock {
+;         int array[10];
+;     } inputValues;
+;
+;     layout(set=0, binding=1, std430) buffer OutputBlock {
+;         int array[10];
+;     } outputValues;
+;
+;     int add_first_and_second (int value, Pair p1, Pair p2) {
+;         return value + p1.first + p2.second;
+;     }
+;
+;     void main() {
+;         uint idx = gl_GlobalInvocationID.x;
+;         outputValues.array[idx] = add_first_and_second(inputValues.array[idx], spec_constant_pair, constant_pair);
+;     }
+;
+; However, both the constant_pair and the spec_constant_pair have one of their members replaced by undefined values.
+;
+                              OpCapability Shader
+                    %std450 = OpExtInstImport "GLSL.std.450"
+                              OpMemoryModel Logical GLSL450
+                              OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
+                              OpExecutionMode %main LocalSize 1 1 1
+                              OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+                              OpDecorate %_arr_int_uint_10 ArrayStride 4
+                              OpMemberDecorate %OutputBlock 0 Offset 0
+                              OpDecorate %OutputBlock BufferBlock
+                              OpDecorate %outputValues DescriptorSet 0
+                              OpDecorate %outputValues Binding 1
+                              OpMemberDecorate %InputBlock 0 Offset 0
+                              OpDecorate %InputBlock BufferBlock
+                              OpDecorate %inputValues DescriptorSet 0
+                              OpDecorate %inputValues Binding 0
+                              OpDecorate %spec_constant SpecId 0
+                      %void = OpTypeVoid
+                 %void_func = OpTypeFunction %void
+                       %int = OpTypeInt 32 1
+                      %uint = OpTypeInt 32 0
+                    %v3uint = OpTypeVector %uint 3
+                     %int_0 = OpConstant %int 0
+                     %int_1 = OpConstant %int 1
+                   %int_200 = OpConstant %int 200
+                    %uint_0 = OpConstant %uint 0
+                   %uint_10 = OpConstant %uint 10
+         %_ptr_Function_int = OpTypePointer Function %int
+                      %Pair = OpTypeStruct %int %int
+        %_ptr_Function_Pair = OpTypePointer Function %Pair
+%add_pair_members_func_type = OpTypeFunction %int %_ptr_Function_int %_ptr_Function_Pair %_ptr_Function_Pair
+        %_ptr_Function_uint = OpTypePointer Function %uint
+         %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+           %_ptr_Input_uint = OpTypePointer Input %uint
+          %_arr_int_uint_10 = OpTypeArray %int %uint_10
+               %OutputBlock = OpTypeStruct %_arr_int_uint_10
+  %_ptr_Uniform_OutputBlock = OpTypePointer Uniform %OutputBlock
+              %outputValues = OpVariable %_ptr_Uniform_OutputBlock Uniform
+                %InputBlock = OpTypeStruct %_arr_int_uint_10
+   %_ptr_Uniform_InputBlock = OpTypePointer Uniform %InputBlock
+               %inputValues = OpVariable %_ptr_Uniform_InputBlock Uniform
+                              ; Replaced %int_100 with an undefined int.
+                 %undef_int = OpUndef %int
+                              ; Composed a spec constant Pair with an undefined int in the second member.
+             %spec_constant = OpSpecConstant %int 0
+           %spec_const_Pair = OpSpecConstantComposite %Pair %spec_constant %undef_int
+                              ; Composed a constant Pair with the undefined int in the first member.
+                %const_Pair = OpConstantComposite %Pair %undef_int %int_200
+          %_ptr_Uniform_int = OpTypePointer Uniform %int
+     %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+                      %main = OpFunction %void None %void_func
+                %main_label = OpLabel
+                   %param_1 = OpVariable %_ptr_Function_int Function
+                   %param_2 = OpVariable %_ptr_Function_Pair Function
+                   %param_3 = OpVariable %_ptr_Function_Pair Function
+                  %gidx_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
+                      %gidx = OpLoad %uint %gidx_ptr
+           %input_value_ptr = OpAccessChain %_ptr_Uniform_int %inputValues %int_0 %gidx
+               %input_value = OpLoad %int %input_value_ptr
+                              OpStore %param_1 %input_value
+                              OpStore %param_2 %spec_const_Pair
+                              OpStore %param_3 %const_Pair
+                              ; Pass the input value as the first argument.
+                              ; Pass the specialization constant Pair as the second argument.
+                              ; Pass the constant Pair as the third argument.
+                    %retval = OpFunctionCall %int %add_pair_members %param_1 %param_2 %param_3
+          %output_value_ptr = OpAccessChain %_ptr_Uniform_int %outputValues %int_0 %gidx
+                              OpStore %output_value_ptr %retval
+                              OpReturn
+                              OpFunctionEnd
+          %add_pair_members = OpFunction %int None %add_pair_members_func_type
+                 %value_ptr = OpFunctionParameter %_ptr_Function_int
+                    %pair_1 = OpFunctionParameter %_ptr_Function_Pair
+                    %pair_2 = OpFunctionParameter %_ptr_Function_Pair
+    %add_pair_members_label = OpLabel
+                     %value = OpLoad %int %value_ptr
+                              ; Access the first struct member from the first pair.
+                              ; Access the second struct member from the second pair.
+                              ; Both should be defined according to the function call above.
+          %pair_1_first_ptr = OpAccessChain %_ptr_Function_int %pair_1 %int_0
+         %pair_2_second_ptr = OpAccessChain %_ptr_Function_int %pair_2 %int_1
+              %pair_1_first = OpLoad %int %pair_1_first_ptr
+             %pair_2_second = OpLoad %int %pair_2_second_ptr
+            %partial_result = OpIAdd %int %value %pair_1_first
+              %final_result = OpIAdd %int %partial_result %pair_2_second
+                              OpReturnValue %final_result
+                              OpFunctionEnd
+
+END
+
+BUFFER input_buffer DATA_TYPE int32 SIZE 10 SERIES_FROM 1000 INC_BY 1
+BUFFER output_buffer DATA_TYPE int32 SIZE 10 FILL 0
+BUFFER reference_buffer DATA_TYPE int32 SIZE 10 SERIES_FROM 1600 INC_BY 1
+
+PIPELINE compute compute_pipeline
+	ATTACH comp SPECIALIZE 0 AS int32 400
+	BIND BUFFER input_buffer AS storage DESCRIPTOR_SET 0 BINDING 0
+	BIND BUFFER output_buffer AS storage DESCRIPTOR_SET 0 BINDING 1
+END
+
+RUN compute_pipeline 10 1 1
+EXPECT output_buffer EQ_BUFFER reference_buffer
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
index a947fdc..5a5d4f7 100644
--- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
@@ -6938,7 +6938,32 @@
 		group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
 	}
 
-		return group.release();
+	// OpUndef with constants.
+	{
+		static const char data_dir[] = "spirv_assembly/instruction/compute/undef";
+
+		static const struct
+		{
+			const std::string name;
+			const std::string desc;
+		} amberCases[] =
+		{
+			{ "undefined_constant_composite",		"OpUndef value in OpConstantComposite"		},
+			{ "undefined_spec_constant_composite",	"OpUndef value in OpSpecConstantComposite"	},
+		};
+
+		for (int i = 0; i < DE_LENGTH_OF_ARRAY(amberCases); ++i)
+		{
+			cts_amber::AmberTestCase *testCase = cts_amber::createAmberTestCase(testCtx,
+																				amberCases[i].name.c_str(),
+																				amberCases[i].desc.c_str(),
+																				data_dir,
+																				amberCases[i].name + ".amber");
+			group->addChild(testCase);
+		}
+	}
+
+	return group.release();
 }
 
 // Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
diff --git a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt
index 94505c5..a7d9191 100644
--- a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt
+++ b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt
Binary files differ
diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt
index a0bf3d5..132e54d 100644
--- a/external/vulkancts/mustpass/master/vk-default.txt
+++ b/external/vulkancts/mustpass/master/vk-default.txt
Binary files differ