Add CTS tests for VK_EXT_application_parameters

New tests:
dEQP-VKSC.sc.application_parameters.*

New command-line option:
--deqp-app-params-input-file=<path>

Components: Vulkan SC, Framework

VK-GL-CTS issue: 3850

Change-Id: I19807696fd3c7fccab3b7f719474c8cfaf62f766
diff --git a/AndroidGen.mk b/AndroidGen.mk
index 161247c..e5e6c92 100644
--- a/AndroidGen.mk
+++ b/AndroidGen.mk
@@ -26,6 +26,7 @@
 	executor/xeXMLWriter.cpp \
 	external/vulkancts/framework/vulkan/vkAllocationCallbackUtil.cpp \
 	external/vulkancts/framework/vulkan/vkApiVersion.cpp \
+	external/vulkancts/framework/vulkan/vkAppParamsUtil.cpp \
 	external/vulkancts/framework/vulkan/vkBarrierUtil.cpp \
 	external/vulkancts/framework/vulkan/vkBinaryRegistry.cpp \
 	external/vulkancts/framework/vulkan/vkBufferWithMemory.cpp \
@@ -387,6 +388,7 @@
 	external/vulkancts/modules/vulkan/robustness/vktRobustnessTests.cpp \
 	external/vulkancts/modules/vulkan/robustness/vktRobustnessUtil.cpp \
 	external/vulkancts/modules/vulkan/robustness/vktRobustnessVertexAccessTests.cpp \
+	external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.cpp \
 	external/vulkancts/modules/vulkan/sc/vktCommandPoolMemoryReservationTests.cpp \
 	external/vulkancts/modules/vulkan/sc/vktDeviceObjectReservationTests.cpp \
 	external/vulkancts/modules/vulkan/sc/vktFaultHandlingTests.cpp \
diff --git a/android/cts/main/vksc-main/sc.txt b/android/cts/main/vksc-main/sc.txt
index 142c9af..d953329 100644
--- a/android/cts/main/vksc-main/sc.txt
+++ b/android/cts/main/vksc-main/sc.txt
@@ -144,6 +144,16 @@
 dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.cb_above_min_limit.size_big.multiple_recording.allocated_size_2
 dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.cb_above_min_limit.size_big.multiple_recording.allocated_size_8
 dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.cb_above_min_limit.size_big.multiple_recording.allocated_size_16
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_vendor_id
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_device_id
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_parameter_key
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_parameter_value
+dEQP-VKSC.sc.application_parameters.create_instance.valid
+dEQP-VKSC.sc.application_parameters.create_device.invalid_vendor_id
+dEQP-VKSC.sc.application_parameters.create_device.invalid_device_id
+dEQP-VKSC.sc.application_parameters.create_device.invalid_parameter_key
+dEQP-VKSC.sc.application_parameters.create_device.invalid_parameter_value
+dEQP-VKSC.sc.application_parameters.create_device.valid
 dEQP-VKSC.sc.api.forbidden_core_commands
 dEQP-VKSC.sc.api.forbidden_core_extensions
 dEQP-VKSC.sc.api.forbidden_promoted_commands
diff --git a/android/cts/main/vksc-master/sc.txt b/android/cts/main/vksc-master/sc.txt
index 72bb3e0..7252d4c 100644
--- a/android/cts/main/vksc-master/sc.txt
+++ b/android/cts/main/vksc-master/sc.txt
@@ -150,3 +150,13 @@
 dEQP-VKSC.sc.object_refresh.query_refreshable_objects
 dEQP-VKSC.sc.object_refresh.refresh_individual_objects
 dEQP-VKSC.sc.object_refresh.refresh_all_objects
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_vendor_id
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_device_id
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_parameter_key
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_parameter_value
+dEQP-VKSC.sc.application_parameters.create_instance.valid
+dEQP-VKSC.sc.application_parameters.create_device.invalid_vendor_id
+dEQP-VKSC.sc.application_parameters.create_device.invalid_device_id
+dEQP-VKSC.sc.application_parameters.create_device.invalid_parameter_key
+dEQP-VKSC.sc.application_parameters.create_device.invalid_parameter_value
+dEQP-VKSC.sc.application_parameters.create_device.valid
diff --git a/external/vulkancts/README.md b/external/vulkancts/README.md
index b139981..5bed651 100644
--- a/external/vulkancts/README.md
+++ b/external/vulkancts/README.md
@@ -360,8 +360,10 @@
 Changes to platform-specific code (mostly under `framework/platform`)
 are allowed. The commit message for each change must include a clear
 description of the change and why it is necessary.
-For Vulkan SC, changes are also permitted to the vksc-pipeline-compiler
-(under `vkscpc/`) and the vksc-server (under `vkscserver/`).
+For Vulkan SC, changes are also permitted to the following:
+- vksc-pipeline-compiler (under `vkscpc/`)
+- vksc-server (under `vkscserver/`)
+- modules/vulkan/sc/vktApplicationParametersTests.cpp (to provide vendor-specific test data)
 
 Bugfixes to the tests are allowed. Before being used for a submission,
 bugfixes must be accepted and merged into the CTS repository.
@@ -856,6 +858,17 @@
     Define minimum size of the command buffer (in bytes) to use (Vulkan SC only)
 	default: '0'
 
+  --deqp-app-params-input-file=<path>
+    File providing default application parameters (Vulkan SC only)
+    default: ''
+
+    The file should contain lines of input in the following format:
+    type ("instance" or "device"), 32-bit vendorID, 32-bit deviceID, 32-bit parameterKey, 64-bit parameterValue
+
+    `type` specifies whether the values will be used for instance or device creation.
+    All the other values should be encoded in hex. For example:
+    instance, 0x01234567, 0x76543210, 0x01234567, 0x0000000076543210
+
   --deqp-command-default-size=<value>
     Define default single command size (in bytes) to use (Vulkan SC only)
 	default: '256'
diff --git a/external/vulkancts/framework/vulkan/CMakeLists.txt b/external/vulkancts/framework/vulkan/CMakeLists.txt
index 4aab8e4..bf7aa39 100644
--- a/external/vulkancts/framework/vulkan/CMakeLists.txt
+++ b/external/vulkancts/framework/vulkan/CMakeLists.txt
@@ -90,6 +90,8 @@
 set(VKUTILNOSHADER_SRCS
 	vkApiVersion.cpp
 	vkApiVersion.hpp
+	vkAppParamsUtil.cpp
+	vkAppParamsUtil.hpp
 	vkBuilderUtil.cpp
 	vkBuilderUtil.hpp
 	vkBarrierUtil.cpp
diff --git a/external/vulkancts/framework/vulkan/vkAppParamsUtil.cpp b/external/vulkancts/framework/vulkan/vkAppParamsUtil.cpp
new file mode 100755
index 0000000..c7911c5
--- /dev/null
+++ b/external/vulkancts/framework/vulkan/vkAppParamsUtil.cpp
@@ -0,0 +1,129 @@
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2022 NVIDIA CORPORATION, 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.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan SC utilities
+ *//*--------------------------------------------------------------------*/
+
+#include "vkAppParamsUtil.hpp"
+
+#include <fstream>
+#include <string>
+#include <sstream>
+
+#ifdef CTS_USES_VULKANSC
+
+namespace vk
+{
+
+std::string trim (const std::string& original)
+{
+	static const std::string whiteSigns = " \t";
+	const auto beg = original.find_first_not_of(whiteSigns);
+	if (beg == std::string::npos)
+		return std::string();
+	const auto end = original.find_last_not_of(whiteSigns);
+	return original.substr(beg, end - beg + 1);
+}
+
+bool readApplicationParameters (std::vector<VkApplicationParametersEXT>& appParams, const tcu::CommandLine& cmdLine, const bool readInstanceAppParams)
+{
+	const char* appParamsInputFilePath = cmdLine.getAppParamsInputFilePath();
+
+	if (appParamsInputFilePath == DE_NULL)
+		return false;
+
+	std::ifstream							file(appParamsInputFilePath);
+	std::vector<std::string>				lines;
+	std::vector<VkApplicationParametersEXT>	tmpAppParams;
+
+	if (file.is_open())
+	{
+		std::string line;
+
+		while (std::getline(file, line))
+			lines.push_back(line);
+
+		file.close();
+	}
+	else
+	{
+		TCU_THROW(InternalError, "Application parameters input file not found from --deqp-app-params-input-file");
+		return false;
+	}
+
+	for (const std::string& line : lines)
+	{
+		if (line.empty())
+			continue;
+
+		std::stringstream			sstream(line);
+		std::string					token;
+		std::vector<std::string>	tokens;
+
+		while (std::getline(sstream, token, ','))
+			tokens.push_back(trim(token));
+
+		if (tokens[0] != "instance" && tokens[0] != "device")
+		{
+			TCU_THROW(InternalError, "Invalid create type from --deqp-app-params-input-file");
+			return false;
+		}
+
+		if ((tokens[0] == "instance" && readInstanceAppParams) || (tokens[0] == "device" && !readInstanceAppParams))
+		{
+			if (tokens.size() == 5)
+			{
+				const VkApplicationParametersEXT appParam =
+				{
+					VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,				// sType
+					DE_NULL,													// pNext
+					static_cast<deUint32>(std::stoul(tokens[1], nullptr, 16)),	// vendorID
+					static_cast<deUint32>(std::stoul(tokens[2], nullptr, 16)),	// deviceID
+					static_cast<deUint32>(std::stoul(tokens[3], nullptr, 16)),	// key
+					static_cast<deUint64>(std::stoul(tokens[4], nullptr, 16))	// value
+				};
+
+				tmpAppParams.push_back(appParam);
+			}
+			else
+			{
+				TCU_THROW(InternalError, "Invalid input format from --deqp-app-params-input-file");
+				return false;
+			}
+		}
+	}
+
+	if (tmpAppParams.empty())
+		return false;
+
+	appParams = tmpAppParams;
+
+	for (size_t ndx = 0; ndx < appParams.size(); ++ndx)
+	{
+		if (ndx != appParams.size() - 1)
+			appParams[ndx].pNext = &appParams[ndx + 1];
+	}
+
+	return true;
+}
+
+} // vk
+
+#endif // CTS_USES_VULKANSC
\ No newline at end of file
diff --git a/external/vulkancts/framework/vulkan/vkAppParamsUtil.hpp b/external/vulkancts/framework/vulkan/vkAppParamsUtil.hpp
new file mode 100755
index 0000000..b83cb6a
--- /dev/null
+++ b/external/vulkancts/framework/vulkan/vkAppParamsUtil.hpp
@@ -0,0 +1,42 @@
+#ifndef _VKAPPPARAMSUTIL_HPP
+#define _VKAPPPARAMSUTIL_HPP
+
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2022 NVIDIA CORPORATION, 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.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan SC utilities
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "tcuCommandLine.hpp"
+#include <vector>
+
+#ifdef CTS_USES_VULKANSC
+
+namespace vk
+{
+
+bool readApplicationParameters (std::vector<VkApplicationParametersEXT>& appParams, const tcu::CommandLine& cmdLine, const bool readInstanceAppParams);
+
+} //vk
+
+#endif // CTS_USES_VULKANSC
+
+#endif // _VKAPPPARAMSUTIL_HPP
diff --git a/external/vulkancts/framework/vulkan/vkDeviceUtil.cpp b/external/vulkancts/framework/vulkan/vkDeviceUtil.cpp
index 024148e..5192262 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceUtil.cpp
+++ b/external/vulkancts/framework/vulkan/vkDeviceUtil.cpp
@@ -32,6 +32,10 @@
 
 #include "qpInfo.h"
 
+#ifdef CTS_USES_VULKANSC
+#include "vkAppParamsUtil.hpp"
+#endif // CTS_USES_VULKANSC
+
 namespace vk
 {
 
@@ -42,6 +46,7 @@
 										deUint32						apiVersion,
 										const vector<string>&			enabledLayers,
 										const vector<string>&			enabledExtensions,
+										const tcu::CommandLine&			cmdLine,
 #ifndef CTS_USES_VULKANSC
 										DebugReportRecorder*			recorder,
 #endif // CTS_USES_VULKANSC
@@ -84,10 +89,21 @@
 	for (size_t ndx = 0; ndx < actualExtensions.size(); ++ndx)
 		extensionNamePtrs[ndx] = actualExtensions[ndx].c_str();
 
-	const struct VkApplicationInfo		appInfo			=
+#ifdef CTS_USES_VULKANSC
+	vector<VkApplicationParametersEXT> appParams;
+	const bool hasAppParams = readApplicationParameters(appParams, cmdLine, true);
+#else
+	DE_UNREF(cmdLine);
+#endif // CTS_USES_VULKANSC
+
+	const struct VkApplicationInfo			appInfo			=
 	{
 		VK_STRUCTURE_TYPE_APPLICATION_INFO,
+#ifdef CTS_USES_VULKANSC
+		hasAppParams ? &appParams[0] : DE_NULL,
+#else
 		DE_NULL,
+#endif // CTS_USES_VULKANSC
 		"deqp",									// pAppName
 		qpGetReleaseId(),						// appVersion
 		"deqp",									// pEngineName
@@ -95,6 +111,7 @@
 		apiVersion								// apiVersion
 	};
 
+
 #ifndef CTS_USES_VULKANSC
 	const VkDebugReportCallbackCreateInfoEXT callbackInfo = (validationEnabled ? recorder->makeCreateInfo() : initVulkanStructure());
 #endif // CTS_USES_VULKANSC
@@ -119,12 +136,12 @@
 	return createInstance(vkPlatform, &instanceInfo, pAllocator);
 }
 
-Move<VkInstance> createDefaultInstance (const PlatformInterface& vkPlatform, deUint32 apiVersion)
+Move<VkInstance> createDefaultInstance (const PlatformInterface& vkPlatform, deUint32 apiVersion, const tcu::CommandLine& cmdLine)
 {
 #ifndef CTS_USES_VULKANSC
-	return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), nullptr, nullptr);
+	return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), cmdLine, nullptr, nullptr);
 #else
-	return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), nullptr);
+	return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), cmdLine, nullptr);
 #endif
 }
 
diff --git a/external/vulkancts/framework/vulkan/vkDeviceUtil.hpp b/external/vulkancts/framework/vulkan/vkDeviceUtil.hpp
index 939c5e7..8244e71 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceUtil.hpp
+++ b/external/vulkancts/framework/vulkan/vkDeviceUtil.hpp
@@ -39,12 +39,14 @@
 {
 
 Move<VkInstance>	createDefaultInstance	(const PlatformInterface&			vkPlatform,
-											 deUint32							apiVersion);
+											 deUint32							apiVersion,
+											 const tcu::CommandLine&				cmdLine);
 
 Move<VkInstance>	createDefaultInstance	(const PlatformInterface&			vkPlatform,
 											 deUint32							apiVersion,
 											 const std::vector<std::string>&	enabledLayers,
 											 const std::vector<std::string>&	enabledExtensions,
+											 const tcu::CommandLine&			cmdLine,
 #ifndef CTS_USES_VULKANSC
 											 DebugReportRecorder*				recorder = nullptr,
 #endif // CTS_USES_VULKANSC
diff --git a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
index 1aa5e1c..3e484af 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
@@ -1791,7 +1791,7 @@
 {
 	const PlatformInterface&				platformInterface		= context.getPlatformInterface();
 	const auto								validationEnabled		= context.getTestContext().getCommandLine().isValidationEnabled();
-	const Unique<VkInstance>				instance				(createDefaultInstance(platformInterface, context.getUsedApiVersion()));
+	const Unique<VkInstance>				instance				(createDefaultInstance(platformInterface, context.getUsedApiVersion(), context.getTestContext().getCommandLine()));
 	const InstanceDriver					instanceDriver			(platformInterface, instance.get());
 	const VkPhysicalDevice					physicalDevice			= chooseDevice(instanceDriver, instance.get(), context.getTestContext().getCommandLine());
 	const deUint32							queueFamilyIndex		= 0;
diff --git a/external/vulkancts/modules/vulkan/sc/CMakeLists.txt b/external/vulkancts/modules/vulkan/sc/CMakeLists.txt
index 8f9ee34..8b17621 100644
--- a/external/vulkancts/modules/vulkan/sc/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/sc/CMakeLists.txt
@@ -17,6 +17,8 @@
 	vktObjectRefreshTests.hpp
 	vktPipelineCacheSCTests.cpp
 	vktPipelineCacheSCTests.hpp
+	vktApplicationParametersTests.cpp
+	vktApplicationParametersTests.hpp
 )
 
 PCH(DEQP_VK_SC_SRCS ../pch.cpp)
diff --git a/external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.cpp b/external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.cpp
new file mode 100755
index 0000000..2a2d70a
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.cpp
@@ -0,0 +1,392 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2022 NVIDIA CORPORATION, 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.
+ *
+ *//*!
+ * \file
+ * \brief  Vulkan SC VK_EXT_application_parameters Tests
+*//*--------------------------------------------------------------------*/
+
+#include "vktApplicationParametersTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+#include "vktCustomInstancesDevices.hpp"
+#include "vkSafetyCriticalUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "tcuTestLog.hpp"
+
+namespace vkt
+{
+namespace sc
+{
+
+using namespace vk;
+
+enum ApplicationParametersCreateType
+{
+	INSTANCE = 0,
+	DEVICE
+};
+
+enum ApplicationParametersTestType
+{
+	INVALID_VENDOR_ID = 0,
+	INVALID_DEVICE_ID,
+	INVALID_PARAM_KEY,
+	INVALID_PARAM_VALUE,
+	VALID
+};
+
+struct TestParams
+{
+	ApplicationParametersCreateType	createType;
+	ApplicationParametersTestType	testType;
+};
+
+struct TestData
+{
+	TestParams	testParams;
+	uint32_t	vendorId;
+	uint32_t	deviceId;
+	uint32_t	paramKey;
+	uint64_t	paramValue;
+	VkResult	expectedResult;
+};
+
+void readIDsFromDevice (Context& context, uint32_t& vendorId, uint32_t& deviceId)
+{
+	const InstanceInterface&	instanceInterface	= context.getInstanceInterface();
+	VkPhysicalDevice			physicalDevice		= context.getPhysicalDevice();
+	VkPhysicalDeviceProperties	properties;
+
+	instanceInterface.getPhysicalDeviceProperties(physicalDevice, &properties);
+
+	vendorId = properties.vendorID;
+	deviceId = properties.deviceID;
+}
+
+TestData getDefaultTestData (Context& context, TestParams testParams)
+{
+	TestData testData{};
+	testData.testParams = testParams;
+
+	readIDsFromDevice(context, testData.vendorId, testData.deviceId);
+
+	switch(testParams.testType)
+	{
+		case INVALID_VENDOR_ID:
+			testData.vendorId = 0x01234567;
+			testData.expectedResult = VK_ERROR_INCOMPATIBLE_DRIVER;
+			break;
+
+		case INVALID_DEVICE_ID:
+			testData.deviceId = 0x01234567;
+			testData.expectedResult = VK_ERROR_INCOMPATIBLE_DRIVER;
+			break;
+
+		case INVALID_PARAM_KEY:
+			testData.paramKey = 0x7fffffff;
+			testData.expectedResult = VK_ERROR_INITIALIZATION_FAILED;
+			break;
+
+		case INVALID_PARAM_VALUE:
+		case VALID:
+			// There is no default test case for the invalid param value and valid tests.
+			// Vendors should provide their own test data for these tests in getTestDataList.
+			break;
+	}
+
+	if (testParams.createType == DEVICE && testParams.testType != VALID)
+		testData.expectedResult = VK_ERROR_INITIALIZATION_FAILED;
+
+	return testData;
+}
+
+std::vector<TestData> getTestDataList(Context& context, TestParams testParams)
+{
+	std::vector<TestData>		testDataList;
+	uint32_t					vendorId;
+	uint32_t					deviceId;
+
+	readIDsFromDevice(context, vendorId, deviceId);
+
+	const std::vector<TestData> vendorTestDataList =
+	{
+		//	The invalid param value and valid tests need to use vendor-specific application
+		//	parameter keys and values. In order to have full test coverage, vendors should
+		//	provide their own test data for the invalid param value and valid tests here.
+		//	For example:
+		//
+		//	{
+		//		{ INSTANCE, INVALID_PARAM_VALUE },
+		//		validVendorID,
+		//		validDeviceID,
+		//		validParamKey,
+		//		invalidParamValue,
+		//		VK_ERROR_INITIALIZATION_FAILED
+		//	},
+		//	{
+		//		{ INSTANCE, VALID },
+		//		validVendorID,
+		//		validDeviceID,
+		//		validParamKey,
+		//		validParamValue,
+		//		VK_SUCCESS
+		//	},
+		//	{
+		//		{ DEVICE, INVALID_PARAM_VALUE },
+		//		validVendorID,
+		//		validDeviceID,
+		//		validParamKey,
+		//		invalidParamValue,
+		//		VK_ERROR_INITIALIZATION_FAILED
+		//	},
+		//	{
+		//		{ DEVICE, VALID },
+		//		validVendorID,
+		//		validDeviceID,
+		//		validParamKey,
+		//		validParamValue,
+		//		VK_SUCCESS
+		//	}
+	};
+
+	if (testParams.testType != INVALID_PARAM_VALUE && testParams.testType != VALID)
+		testDataList.push_back(getDefaultTestData(context, testParams));
+
+	for (TestData vendorTestData : vendorTestDataList)
+	{
+		if (vendorTestData.testParams.createType == testParams.createType &&
+			vendorTestData.testParams.testType == testParams.testType &&
+			vendorTestData.vendorId == vendorId &&
+			(vendorTestData.deviceId == 0 || vendorTestData.deviceId == deviceId))
+		{
+			testDataList.push_back(vendorTestData);
+		}
+	}
+
+	return testDataList;
+}
+
+void checkSupport (Context& context, TestParams testParams)
+{
+	const std::vector<VkExtensionProperties> supportedExtensions = enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL);
+
+	if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_application_parameters")))
+		TCU_THROW(NotSupportedError, "VK_EXT_application_parameters is not supported");
+
+	const std::vector<TestData> testDataList = getTestDataList(context, testParams);
+
+	if (testDataList.empty())
+		TCU_THROW(NotSupportedError, "No test data available");
+}
+
+tcu::TestStatus createDeviceTest (Context& context, TestParams testParams)
+{
+	tcu::TestLog&								log						= context.getTestContext().getLog();
+	const PlatformInterface&					platformInterface		= context.getPlatformInterface();
+	const CustomInstance						instance				(createCustomInstanceFromContext(context));
+	const InstanceDriver&						instanceDriver			(instance.getDriver());
+	const VkPhysicalDevice						physicalDevice			= chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
+	const std::vector<TestData>					testDataList			= getTestDataList(context, testParams);
+	const float									queuePriority			= 1.0f;
+	VkDeviceObjectReservationCreateInfo			devObjectResCreateInfo	= resetDeviceObjectReservationCreateInfo();
+	bool										testPassed				= true;
+	const VkPhysicalDeviceVulkanSC10Features	sc10Features			=
+	{
+		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES,	// sType;
+		&devObjectResCreateInfo,									// pNext;
+		VK_FALSE													// shaderAtomicInstructions;
+	};
+
+	for (TestData testData : testDataList)
+	{
+		const VkApplicationParametersEXT appParams =
+		{
+			VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,
+			&sc10Features,
+			testData.vendorId,
+			testData.deviceId,
+			testData.paramKey,
+			testData.paramValue
+		};
+
+		const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,										// sType
+			DE_NULL,																		// pNext
+			(VkDeviceQueueCreateFlags)0u,													// flags
+			0,																				// queueFamilyIndex;
+			1,																				// queueCount;
+			&queuePriority,																	// pQueuePriorities;
+		};
+
+		VkDeviceCreateInfo deviceCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,											// sType;
+			&appParams,																		// pNext;
+			(VkDeviceCreateFlags)0u,														// flags
+			1,																				// queueRecordCount;
+			&deviceQueueCreateInfo,															// pRequestedQueues;
+			0,																				// layerCount;
+			DE_NULL,																		// ppEnabledLayerNames;
+			0,																				// extensionCount;
+			DE_NULL,																		// ppEnabledExtensionNames;
+			DE_NULL,																		// pEnabledFeatures;
+		};
+
+		log << tcu::TestLog::Message << "Creating device with application parameters: " << appParams << tcu::TestLog::EndMessage;
+
+		VkDevice		device		= (VkDevice)0;
+		const VkResult	result		= instanceDriver.createDevice(physicalDevice, &deviceCreateInfo, DE_NULL, &device);
+
+		if (device)
+		{
+			const DeviceDriver deviceIface(platformInterface, instance, device);
+			deviceIface.destroyDevice(device, DE_NULL/*pAllocator*/);
+		}
+
+		log << tcu::TestLog::Message << "Device creation returned with " + de::toString(getResultName(result)) +
+			" (expecting " + de::toString(getResultName(testData.expectedResult)) + ")" << tcu::TestLog::EndMessage;
+
+		if (result != testData.expectedResult)
+			testPassed = false;
+	}
+
+	if (testPassed)
+		return tcu::TestStatus::pass("Pass");
+	else
+		return tcu::TestStatus::fail("Fail");
+}
+
+tcu::TestStatus createInstanceTest (Context& context, TestParams testParams)
+{
+	tcu::TestLog&				log					= context.getTestContext().getLog();
+	const PlatformInterface&	platformInterface	= context.getPlatformInterface();
+	const std::vector<TestData>	testDataList		= getTestDataList(context, testParams);
+	bool						testPassed			= true;
+
+	for (TestData testData : testDataList)
+	{
+		const VkApplicationParametersEXT appParams
+		{
+			VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,
+			DE_NULL,
+			testData.vendorId,
+			testData.deviceId,
+			testData.paramKey,
+			testData.paramValue
+		};
+
+		const VkApplicationInfo appInfo =
+		{
+			VK_STRUCTURE_TYPE_APPLICATION_INFO,		// VkStructureType				sType;
+			&appParams,								// const void*					pNext;
+			"appName",								// const char*					pAppName;
+			0u,										// deUint32						appVersion;
+			"engineName",							// const char*					pEngineName;
+			0u,										// deUint32						engineVersion;
+			context.getUsedApiVersion(),			// deUint32						apiVersion;
+		};
+
+		const VkInstanceCreateInfo instanceCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,	// VkStructureType				sType;
+			DE_NULL,								// const void*					pNext;
+			(VkInstanceCreateFlags)0u,				// VkInstanceCreateFlags		flags;
+			&appInfo,								// const VkApplicationInfo*		pAppInfo;
+			0u,										// deUint32						layerCount;
+			DE_NULL,								// const char*const*			ppEnabledLayernames;
+			0u,										// deUint32						extensionCount;
+			DE_NULL,								// const char*const*			ppEnabledExtensionNames;
+		};
+
+		log << tcu::TestLog::Message << "Creating instance with application parameters: " << appParams << tcu::TestLog::EndMessage;
+
+		VkInstance				  instance			= (VkInstance)0;
+		const VkResult			  result			= platformInterface.createInstance(&instanceCreateInfo, DE_NULL/*pAllocator*/, &instance);
+
+		if (instance)
+		{
+			const InstanceDriver instanceIface(platformInterface, instance);
+			instanceIface.destroyInstance(instance, DE_NULL/*pAllocator*/);
+		}
+
+		log << tcu::TestLog::Message << "Instance creation returned with " + de::toString(getResultName(result)) +
+			" (expecting " + de::toString(getResultName(testData.expectedResult)) + ")" << tcu::TestLog::EndMessage;
+
+		if (result != testData.expectedResult)
+			testPassed = false;
+	}
+
+	if (testPassed)
+		return tcu::TestStatus::pass("Pass");
+	else
+		return tcu::TestStatus::fail("Fail");
+}
+
+tcu::TestCaseGroup*	createApplicationParametersTests (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "application_parameters", "Tests VK_EXT_application_parameters"));
+
+	const struct
+	{
+		ApplicationParametersCreateType	createType;
+		const char*						name;
+	} groups[2] =
+	{
+		{ INSTANCE,							"create_instance"	},
+		{ DEVICE,							"create_device"		}
+	};
+
+	const struct
+	{
+		ApplicationParametersTestType		testType;
+		const char*							name;
+	} tests[5] =
+	{
+		{ INVALID_VENDOR_ID,				"invalid_vendor_id"			},
+		{ INVALID_DEVICE_ID,				"invalid_device_id"			},
+		{ INVALID_PARAM_KEY,				"invalid_parameter_key"		},
+		{ INVALID_PARAM_VALUE,				"invalid_parameter_value"	},
+		{ VALID,							"valid"						}
+	};
+
+	for (int groupIdx = 0; groupIdx < DE_LENGTH_OF_ARRAY(groups); ++groupIdx)
+	{
+		de::MovePtr<tcu::TestCaseGroup> createGroup(new tcu::TestCaseGroup(testCtx, groups[groupIdx].name, ""));
+
+		for (int testIdx = 0; testIdx < DE_LENGTH_OF_ARRAY(tests); ++testIdx)
+		{
+			TestParams testParams = { groups[groupIdx].createType, tests[testIdx].testType };
+
+			if (testParams.createType == INSTANCE)
+				addFunctionCase(createGroup.get(), tests[testIdx].name, "", checkSupport, createInstanceTest, testParams);
+			else
+				addFunctionCase(createGroup.get(), tests[testIdx].name, "", checkSupport, createDeviceTest, testParams);
+		}
+
+		group->addChild(createGroup.release());
+	}
+
+	return group.release();
+}
+
+} // sc
+
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.hpp b/external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.hpp
new file mode 100755
index 0000000..d7a0794
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/sc/vktApplicationParametersTests.hpp
@@ -0,0 +1,39 @@
+#ifndef _VKTAPPLICATIONPARAMETERSTESTS_HPP
+#define _VKTAPPLICATIONPARAMETERSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2022 NVIDIA CORPORATION, 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.
+ *
+ *//*!
+ * \file
+ * \brief  Vulkan SC VK_EXT_application_parameters Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace sc
+{
+
+tcu::TestCaseGroup*	createApplicationParametersTests (tcu::TestContext& testCtx);
+
+} // sc
+} // vkt
+
+#endif // _VKTAPPLICATIONPARAMETERSTESTS_HPP
diff --git a/external/vulkancts/modules/vulkan/sc/vktSafetyCriticalTests.cpp b/external/vulkancts/modules/vulkan/sc/vktSafetyCriticalTests.cpp
index ad2f002..87cc9d8 100644
--- a/external/vulkancts/modules/vulkan/sc/vktSafetyCriticalTests.cpp
+++ b/external/vulkancts/modules/vulkan/sc/vktSafetyCriticalTests.cpp
@@ -32,6 +32,7 @@
 #include "vktFaultHandlingTests.hpp"
 #include "vktCommandPoolMemoryReservationTests.hpp"
 #include "vktObjectRefreshTests.hpp"
+#include "vktApplicationParametersTests.hpp"
 
 namespace vkt
 {
@@ -52,6 +53,7 @@
 	scTests->addChild(createFaultHandlingTests					(testCtx));
 	scTests->addChild(createCommandPoolMemoryReservationTests	(testCtx));
 	scTests->addChild(createObjectRefreshTests					(testCtx));
+	scTests->addChild(createApplicationParametersTests			(testCtx));
 }
 
 } // anonymous
diff --git a/external/vulkancts/modules/vulkan/vktCustomInstancesDevices.cpp b/external/vulkancts/modules/vulkan/vktCustomInstancesDevices.cpp
index 7384a17..e3a95e8 100644
--- a/external/vulkancts/modules/vulkan/vktCustomInstancesDevices.cpp
+++ b/external/vulkancts/modules/vulkan/vktCustomInstancesDevices.cpp
@@ -323,10 +323,10 @@
 	// Create custom instance.
 	const vector<string> usedExtensionsVec(begin(usedExtensions), end(usedExtensions));
 #ifndef CTS_USES_VULKANSC
-	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, debugReportRecorder.get(), pAllocator);
+	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, cmdLine, debugReportRecorder.get(), pAllocator);
 	return CustomInstance(context, instance, debugReportRecorder);
 #else
-	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, pAllocator);
+	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, cmdLine, pAllocator);
 	return CustomInstance(context, instance);
 #endif // CTS_USES_VULKANSC
 }
diff --git a/external/vulkancts/modules/vulkan/vktTestCase.cpp b/external/vulkancts/modules/vulkan/vktTestCase.cpp
index 7f6fc81..d35971f 100644
--- a/external/vulkancts/modules/vulkan/vktTestCase.cpp
+++ b/external/vulkancts/modules/vulkan/vktTestCase.cpp
@@ -35,6 +35,7 @@
 #include "vkDeviceProperties.hpp"
 #ifdef CTS_USES_VULKANSC
 #include "vkSafetyCriticalUtil.hpp"
+#include "vkAppParamsUtil.hpp"
 #endif // CTS_USES_VULKANSC
 
 #include "tcuCommandLine.hpp"
@@ -172,7 +173,7 @@
 
 std::pair<deUint32, deUint32> determineDeviceVersions(const PlatformInterface& vkp, deUint32 apiVersion, const tcu::CommandLine& cmdLine)
 {
-	Move<VkInstance>						preinstance				= createDefaultInstance(vkp, apiVersion);
+	Move<VkInstance>						preinstance				= createDefaultInstance(vkp, apiVersion, cmdLine);
 	InstanceDriver							preinterface			(vkp, preinstance.get());
 
 	const vector<VkPhysicalDevice>			devices					= enumeratePhysicalDevices(preinterface, preinstance.get());
@@ -192,9 +193,9 @@
 }
 
 #ifndef CTS_USES_VULKANSC
-Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, DebugReportRecorder* recorder)
+Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine, DebugReportRecorder* recorder)
 #else
-Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions)
+Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine)
 #endif // CTS_USES_VULKANSC
 {
 #ifndef CTS_USES_VULKANSC
@@ -221,9 +222,9 @@
 	}
 
 #ifndef CTS_USES_VULKANSC
-	return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions, recorder);
+	return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions, cmdLine, recorder);
 #else
-	return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions);
+	return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions, cmdLine);
 #endif // CTS_USES_VULKANSC
 }
 
@@ -353,6 +354,14 @@
 	}
 	else
 		deviceInfo.pNext = &dmrCI;
+
+	vector<VkApplicationParametersEXT> appParams;
+	if (readApplicationParameters(appParams, cmdLine, false))
+	{
+		appParams[appParams.size() - 1].pNext = deviceInfo.pNext;
+		deviceInfo.pNext = &appParams[0];
+	}
+
 #else
 	DE_UNREF(resourceInterface);
 #endif // CTS_USES_VULKANSC
@@ -492,9 +501,9 @@
 #endif // CTS_USES_VULKANSC
 	, m_instanceExtensions				(addCoreInstanceExtensions(filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL)), m_usedApiVersion))
 #ifndef CTS_USES_VULKANSC
-	, m_instance						(createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, m_debugReportRecorder.get()))
+	, m_instance						(createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, cmdLine, m_debugReportRecorder.get()))
 #else
-	, m_instance						(createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions))
+	, m_instance						(createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, cmdLine))
 #endif // CTS_USES_VULKANSC
 
 #ifndef CTS_USES_VULKANSC
diff --git a/external/vulkancts/mustpass/main/vksc-default/sc.txt b/external/vulkancts/mustpass/main/vksc-default/sc.txt
index 142c9af..d953329 100644
--- a/external/vulkancts/mustpass/main/vksc-default/sc.txt
+++ b/external/vulkancts/mustpass/main/vksc-default/sc.txt
@@ -144,6 +144,16 @@
 dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.cb_above_min_limit.size_big.multiple_recording.allocated_size_2
 dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.cb_above_min_limit.size_big.multiple_recording.allocated_size_8
 dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.cb_above_min_limit.size_big.multiple_recording.allocated_size_16
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_vendor_id
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_device_id
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_parameter_key
+dEQP-VKSC.sc.application_parameters.create_instance.invalid_parameter_value
+dEQP-VKSC.sc.application_parameters.create_instance.valid
+dEQP-VKSC.sc.application_parameters.create_device.invalid_vendor_id
+dEQP-VKSC.sc.application_parameters.create_device.invalid_device_id
+dEQP-VKSC.sc.application_parameters.create_device.invalid_parameter_key
+dEQP-VKSC.sc.application_parameters.create_device.invalid_parameter_value
+dEQP-VKSC.sc.application_parameters.create_device.valid
 dEQP-VKSC.sc.api.forbidden_core_commands
 dEQP-VKSC.sc.api.forbidden_core_extensions
 dEQP-VKSC.sc.api.forbidden_promoted_commands
diff --git a/framework/common/tcuCommandLine.cpp b/framework/common/tcuCommandLine.cpp
index 600aa9e..2b729b4 100644
--- a/framework/common/tcuCommandLine.cpp
+++ b/framework/common/tcuCommandLine.cpp
@@ -121,6 +121,7 @@
 DE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerLogFile,	std::string);
 DE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerFilePrefix,	std::string);
 DE_DECLARE_COMMAND_LINE_OPT(VkLibraryPath,				std::string);
+DE_DECLARE_COMMAND_LINE_OPT(ApplicationParametersInputFile,	std::string);
 
 
 static void parseIntList (const char* src, std::vector<int>* dst)
@@ -248,7 +249,8 @@
 		<< Option<PipelineCompilerOutputFile>	(DE_NULL,	"deqp-pipeline-file",						"Output file with pipeline cache (Vulkan SC only, do not use manually)", "")
 		<< Option<PipelineCompilerLogFile>		(DE_NULL,	"deqp-pipeline-logfile",					"Log file for pipeline compiler (Vulkan SC only, do not use manually)", "")
 		<< Option<PipelineCompilerFilePrefix>	(DE_NULL,	"deqp-pipeline-prefix",						"Prefix for input pipeline compiler files (Vulkan SC only, do not use manually)", "")
-		<< Option<VkLibraryPath>				(DE_NULL,	"deqp-vk-library-path",						"Path to Vulkan library (e.g. loader library vulkan-1.dll)", "");
+		<< Option<VkLibraryPath>				(DE_NULL,	"deqp-vk-library-path",						"Path to Vulkan library (e.g. loader library vulkan-1.dll)", "")
+		<< Option<ApplicationParametersInputFile>    (DE_NULL,       "deqp-app-params-input-file",				"File that provides a default set of application parameters");
 }
 
 void registerLegacyOptions (de::cmdline::Parser& parser)
@@ -1111,6 +1113,14 @@
 		return DE_NULL;
 }
 
+const char* CommandLine::getAppParamsInputFilePath(void) const
+{
+	if (m_cmdLine.hasOption<opt::ApplicationParametersInputFile>())
+		return m_cmdLine.getOption<opt::ApplicationParametersInputFile>().c_str();
+	else
+		return DE_NULL;
+}
+
 static bool checkTestGroupName (const CaseTreeNode* root, const char* groupPath)
 {
 	const CaseTreeNode* node = findNode(root, groupPath);
diff --git a/framework/common/tcuCommandLine.hpp b/framework/common/tcuCommandLine.hpp
index 1701c39..a714acf 100644
--- a/framework/common/tcuCommandLine.hpp
+++ b/framework/common/tcuCommandLine.hpp
@@ -322,6 +322,9 @@
 	//! Path to Vulkan library (e.g. loader library vulkan-1.dll)
 	const char*						getVkLibraryPath			(void) const;
 
+	//! File that provides a default set of application parameters
+	const char*						getAppParamsInputFilePath(void) const;
+
 	/*--------------------------------------------------------------------*//*!
 	 * \brief Creates case list filter
 	 * \param archive Resources