Fix tessellation break when control stage declares but does not use position builtin.

Add SPIRVShaderOutput::isUsed retrieved from shader reflection.
mvk::sizeOfOutput() returns zero if output var is not used.
Update to latest SPIRV-Cross version.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index a7298a3..071c359 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -19,11 +19,14 @@
 
 Released TBD
 
+- Add support for extensions:
+	- `VK_EXT_inline_uniform_block`
 - Support linear filtering when using `vkCmdBlitImage()`.
 - Clamp image copy extents to image extent.
 - Fix crash in `fetchDependencies` on build paths containing spaces.
 - Fix image subresource sizing calculations for heap-based textures.
 - Fix `MTLHeap` memory leak in `MVKDeviceMemory`.
+- Fix tessellation break when control stage declares but does not use position builtin.
 - Support *Xcode 11.2*.
 
 
diff --git a/ExternalRevisions/SPIRV-Cross_repo_revision b/ExternalRevisions/SPIRV-Cross_repo_revision
index 7ab941b..57d5a9f 100644
--- a/ExternalRevisions/SPIRV-Cross_repo_revision
+++ b/ExternalRevisions/SPIRV-Cross_repo_revision
@@ -1 +1 @@
-b10f5d48c959c5600c5e103a6b955b6b1b59cdff
+96a276c2ca86e81530313786e99e2b95623898ca
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 48a3f6e..5dfa27f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -507,9 +507,10 @@
 }
 
 static uint32_t sizeOfOutput(const SPIRVShaderOutput& output) {
+	if ( !output.isUsed ) { return 0; }		// Unused outputs consume no buffer space.
+
 	uint32_t vecWidth = output.vecWidth;
-	// Round up to 4 elements for 3-vectors, since that reflects how Metal lays them out.
-	if (vecWidth == 3) { vecWidth = 4; }
+	if (vecWidth == 3) { vecWidth = 4; }	// Metal 3-vectors consume same as 4-vectors.
 	switch (output.baseType) {
 		case SPIRType::SByte:
 		case SPIRType::UByte:
diff --git a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.cpp b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.cpp
index d6eefce..4a58885 100644
--- a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.cpp
+++ b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.cpp
@@ -129,6 +129,7 @@
 			reflect.set_entry_point(entryName, model);
 		}
 		reflect.compile();
+		reflect.update_active_builtins();
 
 		outputs.clear();
 
@@ -136,11 +137,13 @@
 		parser.get_parsed_ir().for_each_typed_id<SPIRV_CROSS_NAMESPACE::SPIRVariable>([&reflect, &outputs, model, addSat](uint32_t varID, const SPIRV_CROSS_NAMESPACE::SPIRVariable& var) {
 			if (var.storage != spv::StorageClassOutput) { return; }
 
+			bool isUsed = true;
 			const auto* type = &reflect.get_type(reflect.get_type_from_variable(varID).parent_type);
 			bool patch = reflect.has_decoration(varID, spv::DecorationPatch);
 			auto biType = spv::BuiltInMax;
 			if (reflect.has_decoration(varID, spv::DecorationBuiltIn)) {
 				biType = (spv::BuiltIn)reflect.get_decoration(varID, spv::DecorationBuiltIn);
+				isUsed = reflect.has_active_builtin(biType, var.storage);
 			}
 			uint32_t loc = -1;
 			if (reflect.has_decoration(varID, spv::DecorationLocation)) {
@@ -160,30 +163,31 @@
 					patch = reflect.has_member_decoration(type->self, i, spv::DecorationPatch);
 					if (reflect.has_member_decoration(type->self, i, spv::DecorationBuiltIn)) {
 						biType = (spv::BuiltIn)reflect.get_member_decoration(type->self, i, spv::DecorationBuiltIn);
+						isUsed = reflect.has_active_builtin(biType, var.storage);
 					}
 					const SPIRV_CROSS_NAMESPACE::SPIRType& memberType = reflect.get_type(type->member_types[i]);
 					if (memberType.columns > 1) {
 						for (uint32_t i = 0; i < memberType.columns; i++) {
-							outputs.push_back({memberType.basetype, memberType.vecsize, addSat(memberLoc, i), patch, biType});
+							outputs.push_back({memberType.basetype, memberType.vecsize, addSat(memberLoc, i), biType, patch, isUsed});
 						}
 					} else if (!memberType.array.empty()) {
 						for (uint32_t i = 0; i < memberType.array[0]; i++) {
-							outputs.push_back({memberType.basetype, memberType.vecsize, addSat(memberLoc, i), patch, biType});
+							outputs.push_back({memberType.basetype, memberType.vecsize, addSat(memberLoc, i), biType, patch, isUsed});
 						}
 					} else {
-						outputs.push_back({memberType.basetype, memberType.vecsize, memberLoc, patch, biType});
+						outputs.push_back({memberType.basetype, memberType.vecsize, memberLoc, biType, patch, isUsed});
 					}
 				}
 			} else if (type->columns > 1) {
 				for (uint32_t i = 0; i < type->columns; i++) {
-					outputs.push_back({type->basetype, type->vecsize, addSat(loc, i), patch, biType});
+					outputs.push_back({type->basetype, type->vecsize, addSat(loc, i), biType, patch, isUsed});
 				}
 			} else if (!type->array.empty()) {
 				for (uint32_t i = 0; i < type->array[0]; i++) {
-					outputs.push_back({type->basetype, type->vecsize, addSat(loc, i), patch, biType});
+					outputs.push_back({type->basetype, type->vecsize, addSat(loc, i), biType, patch, isUsed});
 				}
 			} else {
-				outputs.push_back({type->basetype, type->vecsize, loc, patch, biType});
+				outputs.push_back({type->basetype, type->vecsize, loc, biType, patch, isUsed});
 			}
 		});
 		// Sort outputs by ascending location.
diff --git a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.h b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.h
index f8867c6..cb85311 100644
--- a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.h
+++ b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVReflection.h
@@ -61,11 +61,14 @@
 		/** The location number of the output. */
 		uint32_t location;
 
+		/** If this is a builtin, the kind of builtin this is. */
+		spv::BuiltIn builtin;
+
 		/** Whether this is a per-patch or per-vertex output. Only meaningful for tessellation control shaders. */
 		bool perPatch;
 
-		/** If this is a builtin, the kind of builtin this is. */
-		spv::BuiltIn builtin;
+		/** Whether this output is actually used (populated) by the shader. */
+		bool isUsed;
 	};
 
 #pragma mark -