VK_KHR_shader_terminate_invocation implementation

This extension adds Vulkan support for the
SPV_KHR_terminate_invocation SPIR-V extension. That SPIR-V
extension provides a new instruction, OpTerminateInvocation,
which causes a shader invocation to immediately terminate
and sets the coverage of shaded samples to 0; only
previously executed instructions will have observable
effects. The OpTerminateInvocation instruction, along with
the OpDemoteToHelperInvocation instruction from the
VK_EXT_shader_demote_to_helper_invocation extension,
together replace the OpKill instruction, which could behave
like either of these instructions. OpTerminateInvocation
provides the behavior required by the GLSL discard statement,
and should be used when available by GLSL compilers and
applications that need the GLSL discard behavior.

Tests: dEQP-VK.rasterization.frag_side_effects.*.terminate_invocation
Tests: dEQP-VK.renderpass.depth_stencil_write_conditions.*terminate*
Bug: b/204499870
Change-Id: I3756f109a5aab15a05bb1f028944408ec30c95fa
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/64448
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 24bc4c6..ead8189 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -231,16 +231,19 @@
 			}
 			break;
 
+		// Termination instructions:
+		case spv::OpKill:
+		case spv::OpTerminateInvocation:
+			analysis.ContainsKill = true;
+			// [[fallthrough]]
+
+		case spv::OpUnreachable:
+
 		// Branch Instructions (subset of Termination Instructions):
 		case spv::OpBranch:
 		case spv::OpBranchConditional:
 		case spv::OpSwitch:
 		case spv::OpReturn:
-			// [[fallthrough]]
-
-		// Termination instruction:
-		case spv::OpKill:
-		case spv::OpUnreachable:
 			{
 				ASSERT(currentBlock != 0);
 				ASSERT(currentFunction != 0);
@@ -249,11 +252,6 @@
 				blockEnd++;
 				functions[currentFunction].blocks[currentBlock] = Block(blockStart, blockEnd);
 				currentBlock = Block::ID(0);
-
-				if(opcode == spv::OpKill)
-				{
-					analysis.ContainsKill = true;
-				}
 			}
 			break;
 
@@ -802,6 +800,7 @@
 				if(!strcmp(ext, "SPV_KHR_device_group")) break;
 				if(!strcmp(ext, "SPV_KHR_multiview")) break;
 				if(!strcmp(ext, "SPV_EXT_demote_to_helper_invocation")) break;
+				if(!strcmp(ext, "SPV_KHR_terminate_invocation")) break;
 				if(!strcmp(ext, "SPV_EXT_shader_stencil_export")) break;
 				if(!strcmp(ext, "SPV_KHR_float_controls")) break;
 				if(!strcmp(ext, "SPV_KHR_integer_dot_product")) break;
@@ -2092,6 +2091,7 @@
 		return EmitFunctionCall(insn, state);
 
 	case spv::OpKill:
+	case spv::OpTerminateInvocation:
 		return EmitKill(insn, state);
 
 	case spv::OpDemoteToHelperInvocation:
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 0bc8087..9b56913 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -328,7 +328,7 @@
 template<typename T>
 static void getPhysicalDeviceShaderTerminateInvocationFeatures(T *features)
 {
-	features->shaderTerminateInvocation = VK_FALSE;
+	features->shaderTerminateInvocation = VK_TRUE;
 }
 
 template<typename T>
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 471b560..c259c5d 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -422,6 +422,7 @@
 	{ { VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME, VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION } },
 	{ { VK_EXT_PRIVATE_DATA_EXTENSION_NAME, VK_EXT_PRIVATE_DATA_SPEC_VERSION } },
 	{ { VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME, VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION } },
+	{ { VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME, VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION } },
 	{ { VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION } },
 	{ { VK_EXT_TOOLING_INFO_EXTENSION_NAME, VK_EXT_TOOLING_INFO_SPEC_VERSION } },
 	{ { VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME, VK_KHR_COPY_COMMANDS_2_SPEC_VERSION } },