1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2020 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2020 Advanced Micro Devices, Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci */
21e5c31af7Sopenharmony_ci/*!
22e5c31af7Sopenharmony_ci * \file
23e5c31af7Sopenharmony_ci * \brief Pipeline Cache Tests
24e5c31af7Sopenharmony_ci */
25e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*/
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci#include "vktPipelineCreationCacheControlTests.hpp"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ci#include "deRandom.hpp"
30e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp"
31e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
32e5c31af7Sopenharmony_ci#include "vkDeviceUtil.hpp"
33e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
34e5c31af7Sopenharmony_ci#include "vktConstexprVectorUtil.hpp"
35e5c31af7Sopenharmony_ci#include "vktTestCase.hpp"
36e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp"
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ci#include <chrono>
39e5c31af7Sopenharmony_ci#include <random>
40e5c31af7Sopenharmony_ci#include <string>
41e5c31af7Sopenharmony_ci#include <vector>
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_cinamespace vkt
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_cinamespace pipeline
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_cinamespace
48e5c31af7Sopenharmony_ci{
49e5c31af7Sopenharmony_ciusing namespace vk;
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_ciusing tcu::StringTemplate;
52e5c31af7Sopenharmony_ciusing tcu::TestCaseGroup;
53e5c31af7Sopenharmony_ciusing tcu::TestContext;
54e5c31af7Sopenharmony_ciusing tcu::TestStatus;
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ciusing ::std::array;
57e5c31af7Sopenharmony_ciusing ::std::string;
58e5c31af7Sopenharmony_ciusing ::std::vector;
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
61e5c31af7Sopenharmony_ci * Elements common to all test types
62e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
63e5c31af7Sopenharmony_cinamespace test_common
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ciusing ::std::chrono::high_resolution_clock;
66e5c31af7Sopenharmony_ciusing ::std::chrono::microseconds;
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_ciusing duration			 = high_resolution_clock::duration;
69e5c31af7Sopenharmony_ciusing UniquePipeline	 = Move<VkPipeline>;
70e5c31af7Sopenharmony_ciusing UniqueShaderModule = Move<VkShaderModule>;
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
73e5c31af7Sopenharmony_ci * \brief Paired Vulkan API result with elapsed duration
74e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
75e5c31af7Sopenharmony_cistruct TimedResult
76e5c31af7Sopenharmony_ci{
77e5c31af7Sopenharmony_ci	VkResult result;
78e5c31af7Sopenharmony_ci	duration elapsed;
79e5c31af7Sopenharmony_ci};
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
82e5c31af7Sopenharmony_ci * \brief Validation function type output from vkCreate*Pipelines()
83e5c31af7Sopenharmony_ci *
84e5c31af7Sopenharmony_ci * \param result - VkResult returned from API call
85e5c31af7Sopenharmony_ci * \param pipeliens - vector of pipelines created
86e5c31af7Sopenharmony_ci * \param elapsed - high_resolution_clock::duration of time elapsed in API
87e5c31af7Sopenharmony_ci * \param reason - output string to give the reason for failure
88e5c31af7Sopenharmony_ci *
89e5c31af7Sopenharmony_ci * \return QP_TEST_RESULT_PASS on success QP_TEST_RESULT_FAIL otherwise
90e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
91e5c31af7Sopenharmony_ciusing Validator = qpTestResult (*)(VkResult, const vector<UniquePipeline>&, duration, string&);
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_cistatic constexpr size_t VALIDATOR_ARRAY_MAX = 4;
94e5c31af7Sopenharmony_ciusing ValidatorArray						= ConstexprVector<Validator, VALIDATOR_ARRAY_MAX>;
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
97e5c31af7Sopenharmony_ci * \brief Run a loop of validation tests and return the result
98e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
99e5c31af7Sopenharmony_citemplate <typename pipelines_t, qpTestResult FAIL_RESULT = QP_TEST_RESULT_FAIL>
100e5c31af7Sopenharmony_ciTestStatus validateResults(VkResult				 result,
101e5c31af7Sopenharmony_ci						   const pipelines_t&	 pipelines,
102e5c31af7Sopenharmony_ci						   duration				 elapsed,
103e5c31af7Sopenharmony_ci						   const ValidatorArray& validators)
104e5c31af7Sopenharmony_ci{
105e5c31af7Sopenharmony_ci	using de::contains;
106e5c31af7Sopenharmony_ci	static constexpr VkResult ALLOWED_RESULTS[] = {VK_SUCCESS, VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT};
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci	string reason;
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	if (contains(DE_ARRAY_BEGIN(ALLOWED_RESULTS), DE_ARRAY_END(ALLOWED_RESULTS), result) == DE_FALSE)
111e5c31af7Sopenharmony_ci	{
112e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"Pipeline creation returned an error result: ${0}"};
113e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, ERROR_MSG.format(result).c_str());
114e5c31af7Sopenharmony_ci	}
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_ci	for (const auto& validator : validators)
117e5c31af7Sopenharmony_ci	{
118e5c31af7Sopenharmony_ci		const auto qpResult = validator(result, pipelines, elapsed, reason);
119e5c31af7Sopenharmony_ci		if (qpResult != QP_TEST_RESULT_PASS)
120e5c31af7Sopenharmony_ci		{
121e5c31af7Sopenharmony_ci			return {qpResult, reason};
122e5c31af7Sopenharmony_ci		}
123e5c31af7Sopenharmony_ci	}
124e5c31af7Sopenharmony_ci
125e5c31af7Sopenharmony_ci	return TestStatus::pass("Test passed.");
126e5c31af7Sopenharmony_ci}
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
129e5c31af7Sopenharmony_ci * \brief Generate an error if result does not match VK_RESULT
130e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
131e5c31af7Sopenharmony_citemplate <VkResult VK_RESULT, qpTestResult FAIL_RESULT = QP_TEST_RESULT_FAIL>
132e5c31af7Sopenharmony_ciqpTestResult checkResult(VkResult result, const vector<UniquePipeline>&, duration, string& reason)
133e5c31af7Sopenharmony_ci{
134e5c31af7Sopenharmony_ci	if (VK_RESULT != result)
135e5c31af7Sopenharmony_ci	{
136e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"Got ${0}, Expected ${1}"};
137e5c31af7Sopenharmony_ci		reason								  = ERROR_MSG.format(result, VK_RESULT);
138e5c31af7Sopenharmony_ci		return FAIL_RESULT;
139e5c31af7Sopenharmony_ci	}
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_ci	return QP_TEST_RESULT_PASS;
142e5c31af7Sopenharmony_ci}
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
145e5c31af7Sopenharmony_ci * \brief Generate an error if pipeline[INDEX] is not valid
146e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
147e5c31af7Sopenharmony_citemplate <size_t INDEX, qpTestResult FAIL_RESULT = QP_TEST_RESULT_FAIL>
148e5c31af7Sopenharmony_ciqpTestResult checkPipelineMustBeValid(VkResult, const vector<UniquePipeline>& pipelines, duration, string& reason)
149e5c31af7Sopenharmony_ci{
150e5c31af7Sopenharmony_ci	if (pipelines.size() <= INDEX)
151e5c31af7Sopenharmony_ci	{
152e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"Index ${0} is not in created pipelines (pipelines.size(): ${1})"};
153e5c31af7Sopenharmony_ci		TCU_THROW(TestError, ERROR_MSG.format(INDEX, pipelines.size()));
154e5c31af7Sopenharmony_ci	}
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	if (*pipelines[INDEX] == VK_NULL_HANDLE)
157e5c31af7Sopenharmony_ci	{
158e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"pipelines[${0}] is not a valid VkPipeline object"};
159e5c31af7Sopenharmony_ci		reason								  = ERROR_MSG.format(INDEX);
160e5c31af7Sopenharmony_ci		return FAIL_RESULT;
161e5c31af7Sopenharmony_ci	}
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci	return QP_TEST_RESULT_PASS;
164e5c31af7Sopenharmony_ci}
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
167e5c31af7Sopenharmony_ci * \brief Generate an error if pipeline[INDEX] is not VK_NULL_HANDLE
168e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
169e5c31af7Sopenharmony_citemplate <size_t INDEX, qpTestResult FAIL_RESULT = QP_TEST_RESULT_FAIL>
170e5c31af7Sopenharmony_ciqpTestResult checkPipelineMustBeNull(VkResult, const vector<UniquePipeline>& pipelines, duration, string& reason)
171e5c31af7Sopenharmony_ci{
172e5c31af7Sopenharmony_ci	if (pipelines.size() <= INDEX)
173e5c31af7Sopenharmony_ci	{
174e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"Index ${0} is not in created pipelines (pipelines.size(): ${1})"};
175e5c31af7Sopenharmony_ci		TCU_THROW(TestError, ERROR_MSG.format(INDEX, pipelines.size()));
176e5c31af7Sopenharmony_ci	}
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci	if (*pipelines[INDEX] != VK_NULL_HANDLE)
179e5c31af7Sopenharmony_ci	{
180e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"pipelines[${0}] is not VK_NULL_HANDLE"};
181e5c31af7Sopenharmony_ci		reason								  = ERROR_MSG.format(INDEX);
182e5c31af7Sopenharmony_ci		return FAIL_RESULT;
183e5c31af7Sopenharmony_ci	}
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	return QP_TEST_RESULT_PASS;
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
189e5c31af7Sopenharmony_ci * \brief Generate an error if any pipeline is valid after an early-return failure
190e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
191e5c31af7Sopenharmony_citemplate <size_t INDEX, qpTestResult FAIL_RESULT = QP_TEST_RESULT_FAIL>
192e5c31af7Sopenharmony_ciqpTestResult checkPipelineNullAfterIndex(VkResult, const vector<UniquePipeline>& pipelines, duration, string& reason)
193e5c31af7Sopenharmony_ci{
194e5c31af7Sopenharmony_ci	if (pipelines.size() <= INDEX)
195e5c31af7Sopenharmony_ci	{
196e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"Index ${0} is not in created pipelines (pipelines.size(): ${1})"};
197e5c31af7Sopenharmony_ci		TCU_THROW(TestError, ERROR_MSG.format(INDEX, pipelines.size()));
198e5c31af7Sopenharmony_ci	}
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	if (pipelines.size() - 1 == INDEX)
201e5c31af7Sopenharmony_ci	{
202e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"Index ${0} is the last pipeline, likely a malformed test case"};
203e5c31af7Sopenharmony_ci		TCU_THROW(TestError, ERROR_MSG.format(INDEX));
204e5c31af7Sopenharmony_ci	}
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_ci	// Only have to iterate through if the requested index is null
207e5c31af7Sopenharmony_ci	if (*pipelines[INDEX] == VK_NULL_HANDLE)
208e5c31af7Sopenharmony_ci	{
209e5c31af7Sopenharmony_ci		for (size_t i = INDEX + 1; i < pipelines.size(); ++i)
210e5c31af7Sopenharmony_ci		{
211e5c31af7Sopenharmony_ci			if (*pipelines[i] != VK_NULL_HANDLE)
212e5c31af7Sopenharmony_ci			{
213e5c31af7Sopenharmony_ci				static const StringTemplate ERROR_MSG = {
214e5c31af7Sopenharmony_ci					"pipelines[${0}] is not VK_NULL_HANDLE after a explicit early return index"};
215e5c31af7Sopenharmony_ci				reason = ERROR_MSG.format(i);
216e5c31af7Sopenharmony_ci				return FAIL_RESULT;
217e5c31af7Sopenharmony_ci			}
218e5c31af7Sopenharmony_ci		}
219e5c31af7Sopenharmony_ci	}
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci	return QP_TEST_RESULT_PASS;
222e5c31af7Sopenharmony_ci}
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
225e5c31af7Sopenharmony_ci * Time limit constants
226e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
227e5c31af7Sopenharmony_cienum ElapsedTime
228e5c31af7Sopenharmony_ci{
229e5c31af7Sopenharmony_ci	ELAPSED_TIME_INFINITE  = microseconds{-1}.count(),
230e5c31af7Sopenharmony_ci	ELAPSED_TIME_IMMEDIATE = microseconds{500}.count(),
231e5c31af7Sopenharmony_ci	ELAPSED_TIME_FAST	   = microseconds{1000}.count()
232e5c31af7Sopenharmony_ci};
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
235e5c31af7Sopenharmony_ci * \brief Generate an error if elapsed time exceeds MAX_TIME
236e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
237e5c31af7Sopenharmony_citemplate <ElapsedTime MAX_TIME, qpTestResult FAIL_RESULT = QP_TEST_RESULT_FAIL>
238e5c31af7Sopenharmony_ciqpTestResult checkElapsedTime(VkResult, const vector<UniquePipeline>&, duration elapsed, string& reason)
239e5c31af7Sopenharmony_ci{
240e5c31af7Sopenharmony_ci#if defined(DE_DEBUG)
241e5c31af7Sopenharmony_ci	DE_UNREF(elapsed);
242e5c31af7Sopenharmony_ci	DE_UNREF(reason);
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci	// In debug mode timing is not likely to be accurate
245e5c31af7Sopenharmony_ci	return QP_TEST_RESULT_PASS;
246e5c31af7Sopenharmony_ci#else
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ci	using ::std::chrono::duration_cast;
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci	static constexpr microseconds ALLOWED_TIME = microseconds{MAX_TIME};
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci	if (elapsed > ALLOWED_TIME)
253e5c31af7Sopenharmony_ci	{
254e5c31af7Sopenharmony_ci		static const StringTemplate ERROR_MSG = {"pipeline creation took longer than ${0}us (actual time: ${1}us)"};
255e5c31af7Sopenharmony_ci		reason = ERROR_MSG.format(ALLOWED_TIME.count(), duration_cast<microseconds>(elapsed).count());
256e5c31af7Sopenharmony_ci		return FAIL_RESULT;
257e5c31af7Sopenharmony_ci	}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci	return QP_TEST_RESULT_PASS;
260e5c31af7Sopenharmony_ci#endif
261e5c31af7Sopenharmony_ci}
262e5c31af7Sopenharmony_ci
263e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
264e5c31af7Sopenharmony_ci * \brief Test case parameters
265e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
266e5c31af7Sopenharmony_cistruct TestParams
267e5c31af7Sopenharmony_ci{
268e5c31af7Sopenharmony_ci	enum CacheType
269e5c31af7Sopenharmony_ci	{
270e5c31af7Sopenharmony_ci		NO_CACHE = 0,
271e5c31af7Sopenharmony_ci		EXPLICIT_CACHE,
272e5c31af7Sopenharmony_ci		DERIVATIVE_HANDLE,
273e5c31af7Sopenharmony_ci		DERIVATIVE_INDEX
274e5c31af7Sopenharmony_ci	};
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci	struct Iteration
277e5c31af7Sopenharmony_ci	{
278e5c31af7Sopenharmony_ci		static constexpr size_t MAX_VARIANTS = 4;
279e5c31af7Sopenharmony_ci		using Variant						 = VkPipelineCreateFlags;
280e5c31af7Sopenharmony_ci		using VariantArray					 = ConstexprVector<Variant, MAX_VARIANTS>;
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_ci		static constexpr Variant NORMAL		  = 0;
283e5c31af7Sopenharmony_ci		static constexpr Variant NO_COMPILE	  = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT;
284e5c31af7Sopenharmony_ci		static constexpr Variant EARLY_RETURN = NO_COMPILE | VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT;
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ci		static constexpr VariantArray SINGLE_NORMAL						= VariantArray{NORMAL};
287e5c31af7Sopenharmony_ci		static constexpr VariantArray SINGLE_NOCOMPILE					= VariantArray{NO_COMPILE};
288e5c31af7Sopenharmony_ci		static constexpr VariantArray BATCH_NOCOMPILE_COMPILE_NOCOMPILE = VariantArray{NO_COMPILE, NORMAL, NO_COMPILE};
289e5c31af7Sopenharmony_ci		static constexpr VariantArray BATCH_RETURN_COMPILE_NOCOMPILE = VariantArray{EARLY_RETURN, NORMAL, NO_COMPILE};
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci		inline constexpr Iteration() : variants{}, validators{} {}
292e5c31af7Sopenharmony_ci		inline constexpr Iteration(const VariantArray& v, const ValidatorArray& f) : variants{v}, validators{f} {}
293e5c31af7Sopenharmony_ci
294e5c31af7Sopenharmony_ci		VariantArray   variants;
295e5c31af7Sopenharmony_ci		ValidatorArray validators;
296e5c31af7Sopenharmony_ci	};
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci	static constexpr size_t MAX_ITERATIONS = 4;
299e5c31af7Sopenharmony_ci	using IterationArray				   = ConstexprVector<Iteration, MAX_ITERATIONS>;
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci	const char*		name;
302e5c31af7Sopenharmony_ci	CacheType		cacheType;
303e5c31af7Sopenharmony_ci	IterationArray	iterations;
304e5c31af7Sopenharmony_ci	bool			useMaintenance5;
305e5c31af7Sopenharmony_ci};
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
308e5c31af7Sopenharmony_ci * \brief Verify extension and feature support
309e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
310e5c31af7Sopenharmony_civoid checkSupport(Context& context, const TestParams& params)
311e5c31af7Sopenharmony_ci{
312e5c31af7Sopenharmony_ci	static constexpr char EXT_NAME[] = "VK_EXT_pipeline_creation_cache_control";
313e5c31af7Sopenharmony_ci	if (!context.requireDeviceFunctionality(EXT_NAME))
314e5c31af7Sopenharmony_ci	{
315e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Extension 'VK_EXT_pipeline_creation_cache_control' is not supported");
316e5c31af7Sopenharmony_ci	}
317e5c31af7Sopenharmony_ci
318e5c31af7Sopenharmony_ci	const auto features = context.getPipelineCreationCacheControlFeatures();
319e5c31af7Sopenharmony_ci	if (features.pipelineCreationCacheControl == DE_FALSE)
320e5c31af7Sopenharmony_ci	{
321e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Feature 'pipelineCreationCacheControl' is not enabled");
322e5c31af7Sopenharmony_ci	}
323e5c31af7Sopenharmony_ci
324e5c31af7Sopenharmony_ci	if (params.useMaintenance5)
325e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_maintenance5");
326e5c31af7Sopenharmony_ci}
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
329e5c31af7Sopenharmony_ci * \brief Generate a random floating point number as a string
330e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
331e5c31af7Sopenharmony_cifloat randomFloat()
332e5c31af7Sopenharmony_ci{
333e5c31af7Sopenharmony_ci#if !defined(DE_DEBUG)
334e5c31af7Sopenharmony_ci	static de::Random state = {::std::random_device{}()};
335e5c31af7Sopenharmony_ci#else
336e5c31af7Sopenharmony_ci	static de::Random state = {0xDEADBEEF};
337e5c31af7Sopenharmony_ci#endif
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_ci	return state.getFloat();
340e5c31af7Sopenharmony_ci}
341e5c31af7Sopenharmony_ci
342e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
343e5c31af7Sopenharmony_ci * \brief Get a string of VkResults from a vector
344e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
345e5c31af7Sopenharmony_cistring getResultsString(const vector<VkResult>& results)
346e5c31af7Sopenharmony_ci{
347e5c31af7Sopenharmony_ci	using ::std::ostringstream;
348e5c31af7Sopenharmony_ci
349e5c31af7Sopenharmony_ci	ostringstream output;
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_ci	output << "results[" << results.size() << "]={ ";
352e5c31af7Sopenharmony_ci
353e5c31af7Sopenharmony_ci	if (!results.empty())
354e5c31af7Sopenharmony_ci	{
355e5c31af7Sopenharmony_ci		output << results[0];
356e5c31af7Sopenharmony_ci	}
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci	for (size_t i = 1; i < results.size(); ++i)
359e5c31af7Sopenharmony_ci	{
360e5c31af7Sopenharmony_ci		output << ", " << results[i];
361e5c31af7Sopenharmony_ci	}
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci	output << " }";
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ci	return output.str();
366e5c31af7Sopenharmony_ci}
367e5c31af7Sopenharmony_ci
368e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
369e5c31af7Sopenharmony_ci * \brief Cast a pointer to an the expected SPIRV type
370e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
371e5c31af7Sopenharmony_citemplate <typename _t>
372e5c31af7Sopenharmony_ciinline const deUint32* shader_cast(const _t* ptr)
373e5c31af7Sopenharmony_ci{
374e5c31af7Sopenharmony_ci	return reinterpret_cast<const deUint32*>(ptr);
375e5c31af7Sopenharmony_ci}
376e5c31af7Sopenharmony_ci
377e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
378e5c31af7Sopenharmony_ci * \brief Capture a container of Vulkan handles into Move<> types
379e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
380e5c31af7Sopenharmony_citemplate <typename input_container_t,
381e5c31af7Sopenharmony_ci		  typename handle_t	 = typename input_container_t::value_type,
382e5c31af7Sopenharmony_ci		  typename move_t	 = Move<handle_t>,
383e5c31af7Sopenharmony_ci		  typename deleter_t = Deleter<handle_t>,
384e5c31af7Sopenharmony_ci		  typename output_t	 = vector<move_t>>
385e5c31af7Sopenharmony_cioutput_t wrapHandles(const DeviceInterface&		  vk,
386e5c31af7Sopenharmony_ci					 VkDevice					  device,
387e5c31af7Sopenharmony_ci					 const input_container_t&	  input,
388e5c31af7Sopenharmony_ci					 const VkAllocationCallbacks* allocator = DE_NULL)
389e5c31af7Sopenharmony_ci{
390e5c31af7Sopenharmony_ci	using ::std::begin;
391e5c31af7Sopenharmony_ci	using ::std::end;
392e5c31af7Sopenharmony_ci	using ::std::transform;
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	auto output = output_t{};
395e5c31af7Sopenharmony_ci	output.resize(input.size());
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	struct Predicate
398e5c31af7Sopenharmony_ci	{
399e5c31af7Sopenharmony_ci		deleter_t deleter;
400e5c31af7Sopenharmony_ci		move_t	  operator()(handle_t v)
401e5c31af7Sopenharmony_ci		{
402e5c31af7Sopenharmony_ci			return (v != VK_NULL_HANDLE) ? move_t{check(v), deleter} : move_t{};
403e5c31af7Sopenharmony_ci		}
404e5c31af7Sopenharmony_ci	};
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci	const auto wrapHandle = Predicate{deleter_t{vk, device, allocator}};
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ci	transform(begin(input), end(input), begin(output), wrapHandle);
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci	return output;
411e5c31af7Sopenharmony_ci}
412e5c31af7Sopenharmony_ci
413e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
414e5c31af7Sopenharmony_ci * \brief create vkPipelineCache for test params
415e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
416e5c31af7Sopenharmony_ciMove<VkPipelineCache> createPipelineCache(const DeviceInterface& vk, VkDevice device, const TestParams& params)
417e5c31af7Sopenharmony_ci{
418e5c31af7Sopenharmony_ci	if (params.cacheType != TestParams::EXPLICIT_CACHE)
419e5c31af7Sopenharmony_ci	{
420e5c31af7Sopenharmony_ci		return {};
421e5c31af7Sopenharmony_ci	}
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci	static constexpr auto cacheInfo = VkPipelineCacheCreateInfo{
424e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, //sType
425e5c31af7Sopenharmony_ci		DE_NULL,									  //pNext
426e5c31af7Sopenharmony_ci		VkPipelineCacheCreateFlags{},				  //flags
427e5c31af7Sopenharmony_ci		deUintptr{0},								  //initialDataSize
428e5c31af7Sopenharmony_ci		DE_NULL										  //pInitialData
429e5c31af7Sopenharmony_ci	};
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci	return createPipelineCache(vk, device, &cacheInfo);
432e5c31af7Sopenharmony_ci}
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
435e5c31af7Sopenharmony_ci * \brief create VkPipelineLayout with descriptor sets from test parameters
436e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
437e5c31af7Sopenharmony_ciMove<VkPipelineLayout> createPipelineLayout(const DeviceInterface&				 vk,
438e5c31af7Sopenharmony_ci											VkDevice							 device,
439e5c31af7Sopenharmony_ci											const vector<VkDescriptorSetLayout>& setLayouts,
440e5c31af7Sopenharmony_ci											const TestParams&)
441e5c31af7Sopenharmony_ci{
442e5c31af7Sopenharmony_ci	const auto layoutCreateInfo = VkPipelineLayoutCreateInfo{
443e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
444e5c31af7Sopenharmony_ci		DE_NULL,									   // pNext
445e5c31af7Sopenharmony_ci		VkPipelineLayoutCreateFlags{},				   // flags
446e5c31af7Sopenharmony_ci		static_cast<deUint32>(setLayouts.size()),	   // setLayoutCount
447e5c31af7Sopenharmony_ci		setLayouts.data(),							   // pSetLayouts
448e5c31af7Sopenharmony_ci		deUint32{0u},								   // pushConstantRangeCount
449e5c31af7Sopenharmony_ci		DE_NULL,									   // pPushConstantRanges
450e5c31af7Sopenharmony_ci	};
451e5c31af7Sopenharmony_ci
452e5c31af7Sopenharmony_ci	return createPipelineLayout(vk, device, &layoutCreateInfo);
453e5c31af7Sopenharmony_ci}
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
456e5c31af7Sopenharmony_ci * \brief create basic VkPipelineLayout from test parameters
457e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
458e5c31af7Sopenharmony_ciMove<VkPipelineLayout> createPipelineLayout(const DeviceInterface& vk, VkDevice device, const TestParams&)
459e5c31af7Sopenharmony_ci{
460e5c31af7Sopenharmony_ci	static constexpr auto layoutCreateInfo = VkPipelineLayoutCreateInfo{
461e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
462e5c31af7Sopenharmony_ci		DE_NULL,									   // pNext
463e5c31af7Sopenharmony_ci		VkPipelineLayoutCreateFlags{},				   // flags
464e5c31af7Sopenharmony_ci		deUint32{0u},								   // setLayoutCount
465e5c31af7Sopenharmony_ci		DE_NULL,									   // pSetLayouts
466e5c31af7Sopenharmony_ci		deUint32{0u},								   // pushConstantRangeCount
467e5c31af7Sopenharmony_ci		DE_NULL,									   // pPushConstantRanges
468e5c31af7Sopenharmony_ci	};
469e5c31af7Sopenharmony_ci
470e5c31af7Sopenharmony_ci	return createPipelineLayout(vk, device, &layoutCreateInfo);
471e5c31af7Sopenharmony_ci}
472e5c31af7Sopenharmony_ci
473e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
474e5c31af7Sopenharmony_ci * \brief Create array of shader modules
475e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
476e5c31af7Sopenharmony_civector<UniqueShaderModule> createShaderModules(const DeviceInterface&	  vk,
477e5c31af7Sopenharmony_ci											   VkDevice					  device,
478e5c31af7Sopenharmony_ci											   const BinaryCollection&	  collection,
479e5c31af7Sopenharmony_ci											   const vector<const char*>& names)
480e5c31af7Sopenharmony_ci{
481e5c31af7Sopenharmony_ci	auto output = vector<UniqueShaderModule>{};
482e5c31af7Sopenharmony_ci	output.reserve(names.size());
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ci	for (const auto& name : names)
485e5c31af7Sopenharmony_ci	{
486e5c31af7Sopenharmony_ci		const auto& binary	   = collection.get(name);
487e5c31af7Sopenharmony_ci		const auto	createInfo = VkShaderModuleCreateInfo{
488e5c31af7Sopenharmony_ci			 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // sType
489e5c31af7Sopenharmony_ci			 DE_NULL,									  // pNext
490e5c31af7Sopenharmony_ci			 VkShaderModuleCreateFlags{},				  // flags
491e5c31af7Sopenharmony_ci			 binary.getSize(),							  // codeSize
492e5c31af7Sopenharmony_ci			 shader_cast(binary.getBinary())			  // pCode
493e5c31af7Sopenharmony_ci		 };
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_ci		output.push_back(createShaderModule(vk, device, &createInfo));
496e5c31af7Sopenharmony_ci	}
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ci	return output;
499e5c31af7Sopenharmony_ci}
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
502e5c31af7Sopenharmony_ci * \brief Create array of shader binding stages
503e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
504e5c31af7Sopenharmony_civector<VkPipelineShaderStageCreateInfo> createShaderStages(const vector<Move<VkShaderModule>>&	modules,
505e5c31af7Sopenharmony_ci														   const vector<VkShaderStageFlagBits>& stages)
506e5c31af7Sopenharmony_ci{
507e5c31af7Sopenharmony_ci	DE_ASSERT(modules.size() == stages.size());
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ci	auto output = vector<VkPipelineShaderStageCreateInfo>{};
510e5c31af7Sopenharmony_ci	output.reserve(modules.size());
511e5c31af7Sopenharmony_ci
512e5c31af7Sopenharmony_ci	int i = 0;
513e5c31af7Sopenharmony_ci
514e5c31af7Sopenharmony_ci	for (const auto& module : modules)
515e5c31af7Sopenharmony_ci	{
516e5c31af7Sopenharmony_ci		const auto stageInfo = VkPipelineShaderStageCreateInfo{
517e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
518e5c31af7Sopenharmony_ci			DE_NULL,											 // pNext
519e5c31af7Sopenharmony_ci			VkPipelineShaderStageCreateFlags{},					 // flags
520e5c31af7Sopenharmony_ci			stages[i++],										 // stage
521e5c31af7Sopenharmony_ci			*module,											 // module
522e5c31af7Sopenharmony_ci			"main",												 // pName
523e5c31af7Sopenharmony_ci			DE_NULL												 // pSpecializationInfo
524e5c31af7Sopenharmony_ci		};
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci		output.push_back(stageInfo);
527e5c31af7Sopenharmony_ci	}
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci	return output;
530e5c31af7Sopenharmony_ci}
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_ci} // namespace test_common
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
535e5c31af7Sopenharmony_ci * \brief Graphics pipeline specific testing
536e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
537e5c31af7Sopenharmony_cinamespace graphics_tests
538e5c31af7Sopenharmony_ci{
539e5c31af7Sopenharmony_ciusing namespace test_common;
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
542e5c31af7Sopenharmony_ci * \brief Common graphics pipeline create info initialization
543e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
544e5c31af7Sopenharmony_ciVkGraphicsPipelineCreateInfo getPipelineCreateInfoCommon()
545e5c31af7Sopenharmony_ci{
546e5c31af7Sopenharmony_ci	static constexpr auto VERTEX_BINDING = VkVertexInputBindingDescription{
547e5c31af7Sopenharmony_ci		deUint32{0u},				// binding
548e5c31af7Sopenharmony_ci		sizeof(float[4]),			// stride
549e5c31af7Sopenharmony_ci		VK_VERTEX_INPUT_RATE_VERTEX // inputRate
550e5c31af7Sopenharmony_ci	};
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	static constexpr auto VERTEX_ATTRIBUTE = VkVertexInputAttributeDescription{
553e5c31af7Sopenharmony_ci		deUint32{0u},				   // location
554e5c31af7Sopenharmony_ci		deUint32{0u},				   // binding
555e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SFLOAT, // format
556e5c31af7Sopenharmony_ci		deUint32{0u}				   // offset
557e5c31af7Sopenharmony_ci	};
558e5c31af7Sopenharmony_ci
559e5c31af7Sopenharmony_ci	static constexpr auto VERTEX_INPUT_STATE = VkPipelineVertexInputStateCreateInfo{
560e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
561e5c31af7Sopenharmony_ci		DE_NULL,												   // pNext
562e5c31af7Sopenharmony_ci		VkPipelineVertexInputStateCreateFlags{},				   // flags
563e5c31af7Sopenharmony_ci		deUint32{1u},											   // vertexBindingDescriptionCount
564e5c31af7Sopenharmony_ci		&VERTEX_BINDING,										   // pVertexBindingDescriptions
565e5c31af7Sopenharmony_ci		deUint32{1u},											   // vertexAttributeDescriptionCount
566e5c31af7Sopenharmony_ci		&VERTEX_ATTRIBUTE										   // pVertexAttributeDescriptions
567e5c31af7Sopenharmony_ci	};
568e5c31af7Sopenharmony_ci
569e5c31af7Sopenharmony_ci	static constexpr auto IA_STATE = VkPipelineInputAssemblyStateCreateInfo{
570e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
571e5c31af7Sopenharmony_ci		DE_NULL,													 // pNext
572e5c31af7Sopenharmony_ci		VkPipelineInputAssemblyStateCreateFlags{},					 // flags
573e5c31af7Sopenharmony_ci		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,						 // topology
574e5c31af7Sopenharmony_ci		VK_TRUE														 // primitiveRestartEnable
575e5c31af7Sopenharmony_ci	};
576e5c31af7Sopenharmony_ci
577e5c31af7Sopenharmony_ci	static constexpr auto TESSALATION_STATE = VkPipelineTessellationStateCreateInfo{
578e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, // sType
579e5c31af7Sopenharmony_ci		DE_NULL,																 // pNext
580e5c31af7Sopenharmony_ci		VkPipelineTessellationStateCreateFlags{},								 // flags
581e5c31af7Sopenharmony_ci		deUint32{0u}															 // patchControlPoints
582e5c31af7Sopenharmony_ci	};
583e5c31af7Sopenharmony_ci
584e5c31af7Sopenharmony_ci	static constexpr auto VIEWPORT = VkViewport{
585e5c31af7Sopenharmony_ci		0.f, // x
586e5c31af7Sopenharmony_ci		0.f, // y
587e5c31af7Sopenharmony_ci		1.f, // width
588e5c31af7Sopenharmony_ci		1.f, // height
589e5c31af7Sopenharmony_ci		0.f, // minDepth
590e5c31af7Sopenharmony_ci		1.f	 // maxDept
591e5c31af7Sopenharmony_ci	};
592e5c31af7Sopenharmony_ci
593e5c31af7Sopenharmony_ci	static constexpr auto SCISSOR_RECT = VkRect2D{
594e5c31af7Sopenharmony_ci		{0, 0},	   // offset
595e5c31af7Sopenharmony_ci		{256, 256} // extent
596e5c31af7Sopenharmony_ci	};
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci	static constexpr auto VIEWPORT_STATE = VkPipelineViewportStateCreateInfo{
599e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType
600e5c31af7Sopenharmony_ci		DE_NULL,											   // pNext
601e5c31af7Sopenharmony_ci		VkPipelineViewportStateCreateFlags{},				   // flags
602e5c31af7Sopenharmony_ci		deUint32{1u},										   // viewportCount
603e5c31af7Sopenharmony_ci		&VIEWPORT,											   // pViewports
604e5c31af7Sopenharmony_ci		deUint32{1u},										   // scissorCount
605e5c31af7Sopenharmony_ci		&SCISSOR_RECT										   // pScissors
606e5c31af7Sopenharmony_ci	};
607e5c31af7Sopenharmony_ci
608e5c31af7Sopenharmony_ci	static constexpr auto RASTERIZATION_STATE = VkPipelineRasterizationStateCreateInfo{
609e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
610e5c31af7Sopenharmony_ci		DE_NULL,													// pNext
611e5c31af7Sopenharmony_ci		VkPipelineRasterizationStateCreateFlags{},					// flags
612e5c31af7Sopenharmony_ci		VK_FALSE,													// depthClampEnable
613e5c31af7Sopenharmony_ci		VK_TRUE,													// rasterizerDiscardEnable
614e5c31af7Sopenharmony_ci		VK_POLYGON_MODE_FILL,										// polygonMode
615e5c31af7Sopenharmony_ci		VK_CULL_MODE_NONE,											// cullMode
616e5c31af7Sopenharmony_ci		VK_FRONT_FACE_CLOCKWISE,									// frontFace
617e5c31af7Sopenharmony_ci		VK_FALSE,													// depthBiasEnable
618e5c31af7Sopenharmony_ci		0.f,														// depthBiasConstantFactor
619e5c31af7Sopenharmony_ci		0.f,														// depthBiasClamp
620e5c31af7Sopenharmony_ci		0.f,														// depthBiasSlopeFactor
621e5c31af7Sopenharmony_ci		1.f															// lineWidth
622e5c31af7Sopenharmony_ci	};
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci	static constexpr auto SAMPLE_MASK = VkSampleMask{};
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_ci	static constexpr auto MULTISAMPLE_STATE = VkPipelineMultisampleStateCreateInfo{
627e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
628e5c31af7Sopenharmony_ci		DE_NULL,												  // pNext
629e5c31af7Sopenharmony_ci		VkPipelineMultisampleStateCreateFlags{},				  // flags
630e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,									  // rasterizationSamples
631e5c31af7Sopenharmony_ci		VK_FALSE,												  // sampleShadingEnable
632e5c31af7Sopenharmony_ci		0.f,													  // minSampleShading
633e5c31af7Sopenharmony_ci		&SAMPLE_MASK,											  // pSampleMask
634e5c31af7Sopenharmony_ci		VK_FALSE,												  // alphaToCoverageEnable
635e5c31af7Sopenharmony_ci		VK_FALSE												  // alphaToOneEnable
636e5c31af7Sopenharmony_ci	};
637e5c31af7Sopenharmony_ci
638e5c31af7Sopenharmony_ci	static constexpr auto STENCIL_OP_STATE = VkStencilOpState{
639e5c31af7Sopenharmony_ci		VK_STENCIL_OP_ZERO,	  // failOp
640e5c31af7Sopenharmony_ci		VK_STENCIL_OP_ZERO,	  // passOp
641e5c31af7Sopenharmony_ci		VK_STENCIL_OP_ZERO,	  // depthFailOp
642e5c31af7Sopenharmony_ci		VK_COMPARE_OP_ALWAYS, // compareOp
643e5c31af7Sopenharmony_ci		deUint32{0u},		  // compareMask
644e5c31af7Sopenharmony_ci		deUint32{0u},		  // writeMask
645e5c31af7Sopenharmony_ci		deUint32{0u}		  // reference
646e5c31af7Sopenharmony_ci	};
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ci	static constexpr auto DEPTH_STENCIL_STATE = VkPipelineDepthStencilStateCreateInfo{
649e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
650e5c31af7Sopenharmony_ci		DE_NULL,													// pNext
651e5c31af7Sopenharmony_ci		VkPipelineDepthStencilStateCreateFlags{},					// flags
652e5c31af7Sopenharmony_ci		VK_FALSE,													// depthTestEnable
653e5c31af7Sopenharmony_ci		VK_FALSE,													// depthWriteEnable
654e5c31af7Sopenharmony_ci		VK_COMPARE_OP_ALWAYS,										// depthCompareOp
655e5c31af7Sopenharmony_ci		VK_FALSE,													// depthBoundsTestEnable
656e5c31af7Sopenharmony_ci		VK_FALSE,													// stencilTestEnable
657e5c31af7Sopenharmony_ci		STENCIL_OP_STATE,											// front
658e5c31af7Sopenharmony_ci		STENCIL_OP_STATE,											// back
659e5c31af7Sopenharmony_ci		0.f,														// minDepthBounds
660e5c31af7Sopenharmony_ci		1.f															// maxDepthBounds
661e5c31af7Sopenharmony_ci	};
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci	static constexpr auto COLOR_FLAGS_ALL = VkColorComponentFlags{VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
664e5c31af7Sopenharmony_ci																  VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
665e5c31af7Sopenharmony_ci
666e5c31af7Sopenharmony_ci	static constexpr auto COLOR_BLEND_ATTACH_STATE = VkPipelineColorBlendAttachmentState{
667e5c31af7Sopenharmony_ci		VK_FALSE,			  // blendEnable
668e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ONE,  // srcColorBlendFactor
669e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ZERO, // dstColorBlendFactor
670e5c31af7Sopenharmony_ci		VK_BLEND_OP_ADD,	  // colorBlendOp
671e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ONE,  // srcAlphaBlendFactor
672e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ZERO, // dstAlphaBlendFactor
673e5c31af7Sopenharmony_ci		VK_BLEND_OP_ADD,	  // alphaBlendOp
674e5c31af7Sopenharmony_ci		COLOR_FLAGS_ALL		  // colorWriteMask
675e5c31af7Sopenharmony_ci	};
676e5c31af7Sopenharmony_ci
677e5c31af7Sopenharmony_ci	static constexpr auto COLOR_BLEND_STATE = VkPipelineColorBlendStateCreateInfo{
678e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
679e5c31af7Sopenharmony_ci		DE_NULL,												  // pNext
680e5c31af7Sopenharmony_ci		VkPipelineColorBlendStateCreateFlags{},					  // flags
681e5c31af7Sopenharmony_ci		VK_FALSE,												  // logicOpEnable
682e5c31af7Sopenharmony_ci		VK_LOGIC_OP_SET,										  // logicOp
683e5c31af7Sopenharmony_ci		deUint32{1u},											  // attachmentCount
684e5c31af7Sopenharmony_ci		&COLOR_BLEND_ATTACH_STATE,								  // pAttachments
685e5c31af7Sopenharmony_ci		{0.f, 0.f, 0.f, 0.f}									  // blendConstants[4]
686e5c31af7Sopenharmony_ci	};
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_ci	static constexpr auto DYNAMIC_STATE = VkPipelineDynamicStateCreateInfo{
689e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType;
690e5c31af7Sopenharmony_ci		DE_NULL,											  // pNext;
691e5c31af7Sopenharmony_ci		VkPipelineDynamicStateCreateFlags{},				  // flags;
692e5c31af7Sopenharmony_ci		deUint32{0u},										  // dynamicStateCount;
693e5c31af7Sopenharmony_ci		DE_NULL												  // pDynamicStates;
694e5c31af7Sopenharmony_ci	};
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci	return VkGraphicsPipelineCreateInfo{
697e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
698e5c31af7Sopenharmony_ci		DE_NULL,										 // pNext
699e5c31af7Sopenharmony_ci		VkPipelineCreateFlags{},						 // flags
700e5c31af7Sopenharmony_ci		deUint32{0u},									 // stageCount
701e5c31af7Sopenharmony_ci		DE_NULL,										 // pStages
702e5c31af7Sopenharmony_ci		&VERTEX_INPUT_STATE,							 // pVertexInputState
703e5c31af7Sopenharmony_ci		&IA_STATE,										 // pInputAssemblyState
704e5c31af7Sopenharmony_ci		&TESSALATION_STATE,								 // pTessellationState
705e5c31af7Sopenharmony_ci		&VIEWPORT_STATE,								 // pViewportState
706e5c31af7Sopenharmony_ci		&RASTERIZATION_STATE,							 // pRasterizationState
707e5c31af7Sopenharmony_ci		&MULTISAMPLE_STATE,								 // pMultisampleState
708e5c31af7Sopenharmony_ci		&DEPTH_STENCIL_STATE,							 // pDepthStencilState
709e5c31af7Sopenharmony_ci		&COLOR_BLEND_STATE,								 // pColorBlendState
710e5c31af7Sopenharmony_ci		&DYNAMIC_STATE,									 // pDynamicState
711e5c31af7Sopenharmony_ci		VK_NULL_HANDLE,									 // layout
712e5c31af7Sopenharmony_ci		VK_NULL_HANDLE,									 // renderPass
713e5c31af7Sopenharmony_ci		deUint32{0u},									 // subpass
714e5c31af7Sopenharmony_ci		VK_NULL_HANDLE,									 // basePipelineHandle
715e5c31af7Sopenharmony_ci		deInt32{-1}										 // basePipelineIndex
716e5c31af7Sopenharmony_ci	};
717e5c31af7Sopenharmony_ci}
718e5c31af7Sopenharmony_ci
719e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
720e5c31af7Sopenharmony_ci * \brief create VkGraphicsPipelineCreateInfo structs from test iteration
721e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
722e5c31af7Sopenharmony_civector<VkGraphicsPipelineCreateInfo> createPipelineCreateInfos(const TestParams::Iteration&		   iteration,
723e5c31af7Sopenharmony_ci															   const VkGraphicsPipelineCreateInfo& base,
724e5c31af7Sopenharmony_ci															   VkPipeline						   basePipeline,
725e5c31af7Sopenharmony_ci															   const TestParams&				   testParameter)
726e5c31af7Sopenharmony_ci{
727e5c31af7Sopenharmony_ci	auto output = vector<VkGraphicsPipelineCreateInfo>{};
728e5c31af7Sopenharmony_ci	output.reserve(iteration.variants.size());
729e5c31af7Sopenharmony_ci
730e5c31af7Sopenharmony_ci	deInt32 count			  = 0;
731e5c31af7Sopenharmony_ci	deInt32 basePipelineIndex = -1;
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_ci	for (VkPipelineCreateFlags flags : iteration.variants)
734e5c31af7Sopenharmony_ci	{
735e5c31af7Sopenharmony_ci		const auto curIndex	  = count++;
736e5c31af7Sopenharmony_ci		auto	   createInfo = base;
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ci		if (testParameter.cacheType == TestParams::DERIVATIVE_INDEX)
739e5c31af7Sopenharmony_ci		{
740e5c31af7Sopenharmony_ci			if (flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT)
741e5c31af7Sopenharmony_ci			{
742e5c31af7Sopenharmony_ci				if (basePipelineIndex != -1)
743e5c31af7Sopenharmony_ci				{
744e5c31af7Sopenharmony_ci					flags |= VK_PIPELINE_CREATE_DERIVATIVE_BIT;
745e5c31af7Sopenharmony_ci				}
746e5c31af7Sopenharmony_ci			}
747e5c31af7Sopenharmony_ci			else
748e5c31af7Sopenharmony_ci			{
749e5c31af7Sopenharmony_ci				flags |= VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
750e5c31af7Sopenharmony_ci
751e5c31af7Sopenharmony_ci				if (basePipelineIndex == -1)
752e5c31af7Sopenharmony_ci				{
753e5c31af7Sopenharmony_ci					basePipelineIndex = curIndex;
754e5c31af7Sopenharmony_ci				}
755e5c31af7Sopenharmony_ci			}
756e5c31af7Sopenharmony_ci		}
757e5c31af7Sopenharmony_ci
758e5c31af7Sopenharmony_ci		createInfo.flags			  = flags;
759e5c31af7Sopenharmony_ci		createInfo.basePipelineHandle = basePipeline;
760e5c31af7Sopenharmony_ci		createInfo.basePipelineIndex  = basePipelineIndex;
761e5c31af7Sopenharmony_ci
762e5c31af7Sopenharmony_ci		output.push_back(createInfo);
763e5c31af7Sopenharmony_ci	}
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci	return output;
766e5c31af7Sopenharmony_ci}
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
769e5c31af7Sopenharmony_ci * \brief create VkRenderPass object for Graphics test
770e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
771e5c31af7Sopenharmony_ciMove<VkRenderPass> createRenderPass(const DeviceInterface& vk, VkDevice device, const TestParams&)
772e5c31af7Sopenharmony_ci{
773e5c31af7Sopenharmony_ci	static constexpr auto COLOR_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
774e5c31af7Sopenharmony_ci
775e5c31af7Sopenharmony_ci	static constexpr auto COLOR_ATTACHMENT_REF = VkAttachmentReference{
776e5c31af7Sopenharmony_ci		deUint32{0u},							 // attachment
777e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // layout
778e5c31af7Sopenharmony_ci	};
779e5c31af7Sopenharmony_ci
780e5c31af7Sopenharmony_ci	static constexpr auto SUBPASS = VkSubpassDescription{
781e5c31af7Sopenharmony_ci		VkSubpassDescriptionFlags{},	 // flags
782e5c31af7Sopenharmony_ci		VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
783e5c31af7Sopenharmony_ci		deUint32{0u},					 // inputAttachmentCount
784e5c31af7Sopenharmony_ci		DE_NULL,						 // pInputAttachments
785e5c31af7Sopenharmony_ci		deUint32{1u},					 // colorAttachmentCount
786e5c31af7Sopenharmony_ci		&COLOR_ATTACHMENT_REF,			 // pColorAttachments
787e5c31af7Sopenharmony_ci		DE_NULL,						 // pResolveAttachments
788e5c31af7Sopenharmony_ci		DE_NULL,						 // pDepthStencilAttachment
789e5c31af7Sopenharmony_ci		deUint32{0u},					 // preserveAttachmentCount
790e5c31af7Sopenharmony_ci		DE_NULL							 // pPreserveAttachments
791e5c31af7Sopenharmony_ci	};
792e5c31af7Sopenharmony_ci
793e5c31af7Sopenharmony_ci	static constexpr auto COLOR_ATTACHMENT = VkAttachmentDescription{
794e5c31af7Sopenharmony_ci		VkAttachmentDescriptionFlags{},	  // flags
795e5c31af7Sopenharmony_ci		COLOR_FORMAT,					  // format
796e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,			  // samples
797e5c31af7Sopenharmony_ci		VK_ATTACHMENT_LOAD_OP_CLEAR,	  // loadOp
798e5c31af7Sopenharmony_ci		VK_ATTACHMENT_STORE_OP_STORE,	  // storeOp
799e5c31af7Sopenharmony_ci		VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // stencilLoadOp
800e5c31af7Sopenharmony_ci		VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
801e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_UNDEFINED,		  // initialLayout
802e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_PRESENT_SRC_KHR	  // finalLayout
803e5c31af7Sopenharmony_ci	};
804e5c31af7Sopenharmony_ci
805e5c31af7Sopenharmony_ci	static constexpr auto RENDER_PASS_CREATE_INFO = VkRenderPassCreateInfo{
806e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
807e5c31af7Sopenharmony_ci		DE_NULL,								   // pNext
808e5c31af7Sopenharmony_ci		VkRenderPassCreateFlags{},				   // flags
809e5c31af7Sopenharmony_ci		deUint32{1u},							   // attachmentCount
810e5c31af7Sopenharmony_ci		&COLOR_ATTACHMENT,						   // pAttachments
811e5c31af7Sopenharmony_ci		deUint32{1u},							   // subpassCount
812e5c31af7Sopenharmony_ci		&SUBPASS,								   // pSubpasses
813e5c31af7Sopenharmony_ci		deUint32{0u},							   // dependencyCount
814e5c31af7Sopenharmony_ci		DE_NULL									   // pDependencies
815e5c31af7Sopenharmony_ci	};
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci	return createRenderPass(vk, device, &RENDER_PASS_CREATE_INFO);
818e5c31af7Sopenharmony_ci}
819e5c31af7Sopenharmony_ci
820e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
821e5c31af7Sopenharmony_ci * \brief Initialize shader programs
822e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
823e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& dst, const TestParams&)
824e5c31af7Sopenharmony_ci{
825e5c31af7Sopenharmony_ci	using ::glu::FragmentSource;
826e5c31af7Sopenharmony_ci	using ::glu::VertexSource;
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci	// Vertex Shader
829e5c31af7Sopenharmony_ci	static const StringTemplate VS_TEXT = {"#version 310 es\n"
830e5c31af7Sopenharmony_ci										   "layout(location = 0) in vec4 position;\n"
831e5c31af7Sopenharmony_ci										   "layout(location = 0) out vec3 vertColor;\n"
832e5c31af7Sopenharmony_ci										   "void main (void)\n"
833e5c31af7Sopenharmony_ci										   "{\n"
834e5c31af7Sopenharmony_ci										   "  gl_Position = position;\n"
835e5c31af7Sopenharmony_ci										   "  vertColor = vec3(${0}, ${1}, ${2});\n"
836e5c31af7Sopenharmony_ci										   "}\n"};
837e5c31af7Sopenharmony_ci
838e5c31af7Sopenharmony_ci	// Fragment Shader
839e5c31af7Sopenharmony_ci	static const StringTemplate FS_TEXT = {"#version 310 es\n"
840e5c31af7Sopenharmony_ci										   "precision highp float;\n"
841e5c31af7Sopenharmony_ci										   "layout(location = 0) in vec3 vertColor;\n"
842e5c31af7Sopenharmony_ci										   "layout(location = 0) out vec4 outColor;\n"
843e5c31af7Sopenharmony_ci										   "void main (void)\n"
844e5c31af7Sopenharmony_ci										   "{\n"
845e5c31af7Sopenharmony_ci										   "  const vec3 fragColor = vec3(${0}, ${1}, ${2});\n"
846e5c31af7Sopenharmony_ci										   "  outColor = vec4((fragColor + vertColor) * 0.5, 1.0);\n"
847e5c31af7Sopenharmony_ci										   "}\n"};
848e5c31af7Sopenharmony_ci
849e5c31af7Sopenharmony_ci	dst.glslSources.add("vertex") << VertexSource{VS_TEXT.format(randomFloat(), randomFloat(), randomFloat())};
850e5c31af7Sopenharmony_ci	dst.glslSources.add("fragment") << FragmentSource{FS_TEXT.format(randomFloat(), randomFloat(), randomFloat())};
851e5c31af7Sopenharmony_ci}
852e5c31af7Sopenharmony_ci
853e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
854e5c31af7Sopenharmony_ci * \brief return both result and elapsed time from pipeline creation
855e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
856e5c31af7Sopenharmony_citemplate <typename create_infos_t, typename pipelines_t>
857e5c31af7Sopenharmony_ciTimedResult timePipelineCreation(const DeviceInterface&		  vk,
858e5c31af7Sopenharmony_ci								 const VkDevice				  device,
859e5c31af7Sopenharmony_ci								 const VkPipelineCache		  cache,
860e5c31af7Sopenharmony_ci								 const create_infos_t&		  createInfos,
861e5c31af7Sopenharmony_ci								 pipelines_t&				  pipelines,
862e5c31af7Sopenharmony_ci								 const VkAllocationCallbacks* pAllocator = DE_NULL)
863e5c31af7Sopenharmony_ci{
864e5c31af7Sopenharmony_ci	DE_ASSERT(createInfos.size() <= pipelines.size());
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci	const auto timeStart = high_resolution_clock::now();
867e5c31af7Sopenharmony_ci	const auto result	 = vk.createGraphicsPipelines(
868e5c31af7Sopenharmony_ci		   device, cache, static_cast<deUint32>(createInfos.size()), createInfos.data(), pAllocator, pipelines.data());
869e5c31af7Sopenharmony_ci	const auto elapsed = high_resolution_clock::now() - timeStart;
870e5c31af7Sopenharmony_ci	return {result, elapsed};
871e5c31af7Sopenharmony_ci}
872e5c31af7Sopenharmony_ci
873e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
874e5c31af7Sopenharmony_ci * \brief Test instance function
875e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
876e5c31af7Sopenharmony_ciTestStatus testInstance(Context& context, const TestParams& testParameter)
877e5c31af7Sopenharmony_ci{
878e5c31af7Sopenharmony_ci	const auto& vk			  = context.getDeviceInterface();
879e5c31af7Sopenharmony_ci	const auto	device		  = context.getDevice();
880e5c31af7Sopenharmony_ci	const auto	pipelineCache = createPipelineCache(vk, device, testParameter);
881e5c31af7Sopenharmony_ci	const auto	layout		  = createPipelineLayout(vk, device, testParameter);
882e5c31af7Sopenharmony_ci	const auto	renderPass	  = createRenderPass(vk, device, testParameter);
883e5c31af7Sopenharmony_ci	// No fragment due to rasterizationDiscardEnabled
884e5c31af7Sopenharmony_ci	const auto	modules		  = createShaderModules(vk, device, context.getBinaryCollection(), std::vector<const char*>{"vertex"});
885e5c31af7Sopenharmony_ci	const auto	shaderStages  = createShaderStages(modules, std::vector<VkShaderStageFlagBits>{VK_SHADER_STAGE_VERTEX_BIT});
886e5c31af7Sopenharmony_ci
887e5c31af7Sopenharmony_ci	// Placeholder for base pipeline if using cacheType == DERIVATIVE_HANDLE
888e5c31af7Sopenharmony_ci	auto basePipeline = UniquePipeline{};
889e5c31af7Sopenharmony_ci
890e5c31af7Sopenharmony_ci	auto baseCreateInfo		  = getPipelineCreateInfoCommon();
891e5c31af7Sopenharmony_ci	baseCreateInfo.layout	  = layout.get();
892e5c31af7Sopenharmony_ci	baseCreateInfo.renderPass = renderPass.get();
893e5c31af7Sopenharmony_ci	baseCreateInfo.stageCount = static_cast<deUint32>(shaderStages.size());
894e5c31af7Sopenharmony_ci	baseCreateInfo.pStages	  = shaderStages.data();
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_ci	auto results = vector<VkResult>{};
897e5c31af7Sopenharmony_ci	results.reserve(testParameter.iterations.size());
898e5c31af7Sopenharmony_ci
899e5c31af7Sopenharmony_ci	for (const auto& i : testParameter.iterations)
900e5c31af7Sopenharmony_ci	{
901e5c31af7Sopenharmony_ci		auto createInfos	= createPipelineCreateInfos(i, baseCreateInfo, basePipeline.get(), testParameter);
902e5c31af7Sopenharmony_ci		auto created		= vector<VkPipeline>{};
903e5c31af7Sopenharmony_ci		created.resize(createInfos.size());
904e5c31af7Sopenharmony_ci
905e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
906e5c31af7Sopenharmony_ci		std::vector<VkPipelineCreateFlags2CreateInfoKHR> flags2CreateInfo(created.size(), { VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR, 0, 0 });
907e5c31af7Sopenharmony_ci		if (testParameter.useMaintenance5)
908e5c31af7Sopenharmony_ci		{
909e5c31af7Sopenharmony_ci			for (deUint32 ci = 0; ci < createInfos.size(); ++ci)
910e5c31af7Sopenharmony_ci			{
911e5c31af7Sopenharmony_ci				flags2CreateInfo[ci].flags	= translateCreateFlag(createInfos[ci].flags);
912e5c31af7Sopenharmony_ci				flags2CreateInfo[ci].pNext  = createInfos[ci].pNext;
913e5c31af7Sopenharmony_ci				createInfos[ci].flags		= 0;
914e5c31af7Sopenharmony_ci				createInfos[ci].pNext		= &flags2CreateInfo[ci];
915e5c31af7Sopenharmony_ci			}
916e5c31af7Sopenharmony_ci		}
917e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
918e5c31af7Sopenharmony_ci
919e5c31af7Sopenharmony_ci		const auto timedResult = timePipelineCreation(vk, device, pipelineCache.get(), createInfos, created);
920e5c31af7Sopenharmony_ci		auto	   pipelines   = wrapHandles(vk, device, created);
921e5c31af7Sopenharmony_ci
922e5c31af7Sopenharmony_ci		const auto status = validateResults(timedResult.result, pipelines, timedResult.elapsed, i.validators);
923e5c31af7Sopenharmony_ci		if (status.getCode() != QP_TEST_RESULT_PASS)
924e5c31af7Sopenharmony_ci		{
925e5c31af7Sopenharmony_ci			return status;
926e5c31af7Sopenharmony_ci		}
927e5c31af7Sopenharmony_ci
928e5c31af7Sopenharmony_ci		if ((testParameter.cacheType == TestParams::DERIVATIVE_HANDLE) && (*basePipeline == VK_NULL_HANDLE))
929e5c31af7Sopenharmony_ci		{
930e5c31af7Sopenharmony_ci			for (auto& pipeline : pipelines)
931e5c31af7Sopenharmony_ci			{
932e5c31af7Sopenharmony_ci				if (*pipeline != VK_NULL_HANDLE)
933e5c31af7Sopenharmony_ci				{
934e5c31af7Sopenharmony_ci					basePipeline = pipeline;
935e5c31af7Sopenharmony_ci					break;
936e5c31af7Sopenharmony_ci				}
937e5c31af7Sopenharmony_ci			}
938e5c31af7Sopenharmony_ci		}
939e5c31af7Sopenharmony_ci
940e5c31af7Sopenharmony_ci		results.push_back(timedResult.result);
941e5c31af7Sopenharmony_ci	}
942e5c31af7Sopenharmony_ci
943e5c31af7Sopenharmony_ci	static const StringTemplate PASS_MSG = {"Test Passed. ${0}"};
944e5c31af7Sopenharmony_ci	return TestStatus::pass(PASS_MSG.format(getResultsString(results)));
945e5c31af7Sopenharmony_ci}
946e5c31af7Sopenharmony_ci
947e5c31af7Sopenharmony_ci} // namespace graphics_tests
948e5c31af7Sopenharmony_ci
949e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
950e5c31af7Sopenharmony_ci * \brief Compute pipeline specific testing
951e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
952e5c31af7Sopenharmony_cinamespace compute_tests
953e5c31af7Sopenharmony_ci{
954e5c31af7Sopenharmony_ciusing namespace test_common;
955e5c31af7Sopenharmony_ci
956e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
957e5c31af7Sopenharmony_ci * \brief create VkComputePipelineCreateInfo structs from test iteration
958e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
959e5c31af7Sopenharmony_civector<VkComputePipelineCreateInfo> createPipelineCreateInfos(const TestParams::Iteration&		 iteration,
960e5c31af7Sopenharmony_ci															  const VkComputePipelineCreateInfo& base,
961e5c31af7Sopenharmony_ci															  VkPipeline						 basePipeline,
962e5c31af7Sopenharmony_ci															  const TestParams&					 testParameter)
963e5c31af7Sopenharmony_ci{
964e5c31af7Sopenharmony_ci	auto output = vector<VkComputePipelineCreateInfo>{};
965e5c31af7Sopenharmony_ci	output.reserve(iteration.variants.size());
966e5c31af7Sopenharmony_ci
967e5c31af7Sopenharmony_ci	deInt32 count			  = 0;
968e5c31af7Sopenharmony_ci	deInt32 basePipelineIndex = -1;
969e5c31af7Sopenharmony_ci
970e5c31af7Sopenharmony_ci	for (VkPipelineCreateFlags flags : iteration.variants)
971e5c31af7Sopenharmony_ci	{
972e5c31af7Sopenharmony_ci		const auto curIndex	  = count++;
973e5c31af7Sopenharmony_ci		auto	   createInfo = base;
974e5c31af7Sopenharmony_ci
975e5c31af7Sopenharmony_ci		if (testParameter.cacheType == TestParams::DERIVATIVE_INDEX)
976e5c31af7Sopenharmony_ci		{
977e5c31af7Sopenharmony_ci			if (flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT)
978e5c31af7Sopenharmony_ci			{
979e5c31af7Sopenharmony_ci				if (basePipelineIndex != -1)
980e5c31af7Sopenharmony_ci				{
981e5c31af7Sopenharmony_ci					flags |= VK_PIPELINE_CREATE_DERIVATIVE_BIT;
982e5c31af7Sopenharmony_ci				}
983e5c31af7Sopenharmony_ci			}
984e5c31af7Sopenharmony_ci			else
985e5c31af7Sopenharmony_ci			{
986e5c31af7Sopenharmony_ci				flags |= VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
987e5c31af7Sopenharmony_ci
988e5c31af7Sopenharmony_ci				if (basePipelineIndex == -1)
989e5c31af7Sopenharmony_ci				{
990e5c31af7Sopenharmony_ci					basePipelineIndex = curIndex;
991e5c31af7Sopenharmony_ci				}
992e5c31af7Sopenharmony_ci			}
993e5c31af7Sopenharmony_ci		}
994e5c31af7Sopenharmony_ci
995e5c31af7Sopenharmony_ci		createInfo.flags			  = flags;
996e5c31af7Sopenharmony_ci		createInfo.basePipelineHandle = basePipeline;
997e5c31af7Sopenharmony_ci		createInfo.basePipelineIndex  = basePipelineIndex;
998e5c31af7Sopenharmony_ci
999e5c31af7Sopenharmony_ci		output.push_back(createInfo);
1000e5c31af7Sopenharmony_ci	}
1001e5c31af7Sopenharmony_ci
1002e5c31af7Sopenharmony_ci	return output;
1003e5c31af7Sopenharmony_ci}
1004e5c31af7Sopenharmony_ci
1005e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1006e5c31af7Sopenharmony_ci * \brief create compute descriptor set layout
1007e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1008e5c31af7Sopenharmony_ciMove<VkDescriptorSetLayout> createDescriptorSetLayout(const DeviceInterface& vk, VkDevice device, const TestParams&)
1009e5c31af7Sopenharmony_ci{
1010e5c31af7Sopenharmony_ci	static constexpr auto DESCRIPTOR_SET_LAYOUT_BINDING = VkDescriptorSetLayoutBinding{
1011e5c31af7Sopenharmony_ci		deUint32{0u},					   // binding
1012e5c31af7Sopenharmony_ci		VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1013e5c31af7Sopenharmony_ci		deUint32{1u},					   // descriptorCount
1014e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_COMPUTE_BIT,	   // stageFlags
1015e5c31af7Sopenharmony_ci		DE_NULL							   // pImmutableSamplers
1016e5c31af7Sopenharmony_ci	};
1017e5c31af7Sopenharmony_ci
1018e5c31af7Sopenharmony_ci	static constexpr auto DESCRIPTOR_SET_LAYOUT_CREATE_INFO = VkDescriptorSetLayoutCreateInfo{
1019e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1020e5c31af7Sopenharmony_ci		DE_NULL,											 // pNext
1021e5c31af7Sopenharmony_ci		VkDescriptorSetLayoutCreateFlags{},					 // flags
1022e5c31af7Sopenharmony_ci		deUint32{1u},										 // bindingCount
1023e5c31af7Sopenharmony_ci		&DESCRIPTOR_SET_LAYOUT_BINDING						 // pBindings
1024e5c31af7Sopenharmony_ci	};
1025e5c31af7Sopenharmony_ci
1026e5c31af7Sopenharmony_ci	return createDescriptorSetLayout(vk, device, &DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
1027e5c31af7Sopenharmony_ci}
1028e5c31af7Sopenharmony_ci
1029e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1030e5c31af7Sopenharmony_ci * \brief Initialize shader programs
1031e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1032e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& dst, const TestParams&)
1033e5c31af7Sopenharmony_ci{
1034e5c31af7Sopenharmony_ci	using ::glu::ComputeSource;
1035e5c31af7Sopenharmony_ci
1036e5c31af7Sopenharmony_ci	static const StringTemplate CS_TEXT = {"#version 450\n"
1037e5c31af7Sopenharmony_ci										   "precision highp float;\n"
1038e5c31af7Sopenharmony_ci										   "layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;\n"
1039e5c31af7Sopenharmony_ci										   "layout (std140, binding = 0) buffer buf { vec3 data[]; };\n"
1040e5c31af7Sopenharmony_ci										   "void main (void)\n"
1041e5c31af7Sopenharmony_ci										   "{\n"
1042e5c31af7Sopenharmony_ci										   "  data[gl_GlobalInvocationID.x] = vec3(${0}, ${1}, ${2});\n"
1043e5c31af7Sopenharmony_ci										   "}\n"};
1044e5c31af7Sopenharmony_ci
1045e5c31af7Sopenharmony_ci	dst.glslSources.add("compute")
1046e5c31af7Sopenharmony_ci		<< ComputeSource{CS_TEXT.format(randomFloat(), randomFloat(), randomFloat())};
1047e5c31af7Sopenharmony_ci}
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1050e5c31af7Sopenharmony_ci * \brief return both result and elapsed time from pipeline creation
1051e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1052e5c31af7Sopenharmony_citemplate <typename create_infos_t, typename pipelines_t>
1053e5c31af7Sopenharmony_ciTimedResult timePipelineCreation(const DeviceInterface&		  vk,
1054e5c31af7Sopenharmony_ci								 const VkDevice				  device,
1055e5c31af7Sopenharmony_ci								 const VkPipelineCache		  cache,
1056e5c31af7Sopenharmony_ci								 const create_infos_t&		  createInfos,
1057e5c31af7Sopenharmony_ci								 pipelines_t&				  pipelines,
1058e5c31af7Sopenharmony_ci								 const VkAllocationCallbacks* pAllocator = DE_NULL)
1059e5c31af7Sopenharmony_ci{
1060e5c31af7Sopenharmony_ci	DE_ASSERT(createInfos.size() <= pipelines.size());
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_ci	const auto timeStart = high_resolution_clock::now();
1063e5c31af7Sopenharmony_ci	const auto result	 = vk.createComputePipelines(
1064e5c31af7Sopenharmony_ci		   device, cache, static_cast<deUint32>(createInfos.size()), createInfos.data(), pAllocator, pipelines.data());
1065e5c31af7Sopenharmony_ci	const auto elapsed = high_resolution_clock::now() - timeStart;
1066e5c31af7Sopenharmony_ci	return {result, elapsed};
1067e5c31af7Sopenharmony_ci}
1068e5c31af7Sopenharmony_ci
1069e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1070e5c31af7Sopenharmony_ci * \brief Test instance function
1071e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1072e5c31af7Sopenharmony_ciTestStatus testInstance(Context& context, const TestParams& testParameter)
1073e5c31af7Sopenharmony_ci{
1074e5c31af7Sopenharmony_ci	const auto& vk					= context.getDeviceInterface();
1075e5c31af7Sopenharmony_ci	const auto	device				= context.getDevice();
1076e5c31af7Sopenharmony_ci	const auto	pipelineCache		= createPipelineCache(vk, device, testParameter);
1077e5c31af7Sopenharmony_ci	const auto	descriptorSetLayout = createDescriptorSetLayout(vk, device, testParameter);
1078e5c31af7Sopenharmony_ci	const auto	pipelineLayout		= createPipelineLayout(vk, device, {descriptorSetLayout.get()}, testParameter);
1079e5c31af7Sopenharmony_ci	const auto	modules				= createShaderModules(vk, device, context.getBinaryCollection(), {"compute"});
1080e5c31af7Sopenharmony_ci	const auto	shaderStages		= createShaderStages(modules, {VK_SHADER_STAGE_COMPUTE_BIT});
1081e5c31af7Sopenharmony_ci
1082e5c31af7Sopenharmony_ci	// Placeholder for base pipeline if using cacheType == DERIVATIVE_HANDLE
1083e5c31af7Sopenharmony_ci	auto basePipeline = UniquePipeline{};
1084e5c31af7Sopenharmony_ci
1085e5c31af7Sopenharmony_ci	const auto baseCreateInfo = VkComputePipelineCreateInfo{
1086e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
1087e5c31af7Sopenharmony_ci		DE_NULL,										// pNext
1088e5c31af7Sopenharmony_ci		VkPipelineCreateFlags{},						// flags
1089e5c31af7Sopenharmony_ci		shaderStages[0],								// stage
1090e5c31af7Sopenharmony_ci		pipelineLayout.get(),							// layout
1091e5c31af7Sopenharmony_ci		VK_NULL_HANDLE,									// basePipelineHandle
1092e5c31af7Sopenharmony_ci		deInt32{-1}										// basePipelineIndex
1093e5c31af7Sopenharmony_ci	};
1094e5c31af7Sopenharmony_ci
1095e5c31af7Sopenharmony_ci	auto results = vector<VkResult>{};
1096e5c31af7Sopenharmony_ci	results.reserve(testParameter.iterations.size());
1097e5c31af7Sopenharmony_ci
1098e5c31af7Sopenharmony_ci	for (const auto& i : testParameter.iterations)
1099e5c31af7Sopenharmony_ci	{
1100e5c31af7Sopenharmony_ci		const auto createInfos = createPipelineCreateInfos(i, baseCreateInfo, basePipeline.get(), testParameter);
1101e5c31af7Sopenharmony_ci		auto	   created	   = vector<VkPipeline>{};
1102e5c31af7Sopenharmony_ci		created.resize(createInfos.size());
1103e5c31af7Sopenharmony_ci
1104e5c31af7Sopenharmony_ci		const auto timedResult = timePipelineCreation(vk, device, pipelineCache.get(), createInfos, created);
1105e5c31af7Sopenharmony_ci		auto	   pipelines   = wrapHandles(vk, device, created);
1106e5c31af7Sopenharmony_ci
1107e5c31af7Sopenharmony_ci		const auto status = validateResults(timedResult.result, pipelines, timedResult.elapsed, i.validators);
1108e5c31af7Sopenharmony_ci		if (status.getCode() != QP_TEST_RESULT_PASS)
1109e5c31af7Sopenharmony_ci		{
1110e5c31af7Sopenharmony_ci			return status;
1111e5c31af7Sopenharmony_ci		}
1112e5c31af7Sopenharmony_ci
1113e5c31af7Sopenharmony_ci		if ((testParameter.cacheType == TestParams::DERIVATIVE_HANDLE) && (*basePipeline == VK_NULL_HANDLE))
1114e5c31af7Sopenharmony_ci		{
1115e5c31af7Sopenharmony_ci			for (auto& pipeline : pipelines)
1116e5c31af7Sopenharmony_ci			{
1117e5c31af7Sopenharmony_ci				if (*pipeline != VK_NULL_HANDLE)
1118e5c31af7Sopenharmony_ci				{
1119e5c31af7Sopenharmony_ci					basePipeline = pipeline;
1120e5c31af7Sopenharmony_ci					break;
1121e5c31af7Sopenharmony_ci				}
1122e5c31af7Sopenharmony_ci			}
1123e5c31af7Sopenharmony_ci		}
1124e5c31af7Sopenharmony_ci
1125e5c31af7Sopenharmony_ci		results.push_back(timedResult.result);
1126e5c31af7Sopenharmony_ci	}
1127e5c31af7Sopenharmony_ci
1128e5c31af7Sopenharmony_ci	static const StringTemplate PASS_MSG = {"Test Passed. ${0}"};
1129e5c31af7Sopenharmony_ci	return TestStatus::pass(PASS_MSG.format(getResultsString(results)));
1130e5c31af7Sopenharmony_ci}
1131e5c31af7Sopenharmony_ci
1132e5c31af7Sopenharmony_ci} // namespace compute_tests
1133e5c31af7Sopenharmony_ci
1134e5c31af7Sopenharmony_ciusing namespace test_common;
1135e5c31af7Sopenharmony_ci
1136e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1137e5c31af7Sopenharmony_ci * \brief Duplicate single pipeline recreation with explicit caching
1138e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1139e5c31af7Sopenharmony_cistatic constexpr TestParams DUPLICATE_SINGLE_RECREATE_EXPLICIT_CACHING =
1140e5c31af7Sopenharmony_ci{
1141e5c31af7Sopenharmony_ci	"duplicate_single_recreate_explicit_caching",
1142e5c31af7Sopenharmony_ci	TestParams::EXPLICIT_CACHE,
1143e5c31af7Sopenharmony_ci	TestParams::IterationArray
1144e5c31af7Sopenharmony_ci	{
1145e5c31af7Sopenharmony_ci		TestParams::Iteration{
1146e5c31af7Sopenharmony_ci			// Iteration [0]: Force compilation of pipeline
1147e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NORMAL,
1148e5c31af7Sopenharmony_ci			ValidatorArray{
1149e5c31af7Sopenharmony_ci				// Fail if result is not VK_SUCCESS
1150e5c31af7Sopenharmony_ci				checkResult<VK_SUCCESS>,
1151e5c31af7Sopenharmony_ci				// Fail if pipeline is not valid
1152e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<0>
1153e5c31af7Sopenharmony_ci			}
1154e5c31af7Sopenharmony_ci		},
1155e5c31af7Sopenharmony_ci		TestParams::Iteration{
1156e5c31af7Sopenharmony_ci			// Iteration [1]: Request compilation of same pipeline without compile
1157e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NOCOMPILE,
1158e5c31af7Sopenharmony_ci			ValidatorArray{
1159e5c31af7Sopenharmony_ci				// Warn if result is not VK_SUCCESS
1160e5c31af7Sopenharmony_ci				checkResult<VK_SUCCESS, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1161e5c31af7Sopenharmony_ci				// Warn if pipeline is not valid
1162e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<0, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1163e5c31af7Sopenharmony_ci				// Warn if pipeline took too long
1164e5c31af7Sopenharmony_ci				checkElapsedTime<ELAPSED_TIME_FAST, QP_TEST_RESULT_QUALITY_WARNING>
1165e5c31af7Sopenharmony_ci			}
1166e5c31af7Sopenharmony_ci		}
1167e5c31af7Sopenharmony_ci	},
1168e5c31af7Sopenharmony_ci	false
1169e5c31af7Sopenharmony_ci};
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1172e5c31af7Sopenharmony_ci * \brief Duplicate single pipeline recreation with no explicit cache
1173e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1174e5c31af7Sopenharmony_cistatic constexpr TestParams DUPLICATE_SINGLE_RECREATE_NO_CACHING =
1175e5c31af7Sopenharmony_ci{
1176e5c31af7Sopenharmony_ci	"duplicate_single_recreate_no_caching",
1177e5c31af7Sopenharmony_ci	TestParams::NO_CACHE,
1178e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1179e5c31af7Sopenharmony_ci		TestParams::Iteration{
1180e5c31af7Sopenharmony_ci			// Iteration [0]: Force compilation of pipeline
1181e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NORMAL,
1182e5c31af7Sopenharmony_ci			ValidatorArray{
1183e5c31af7Sopenharmony_ci				// Fail if result is not VK_SUCCESS
1184e5c31af7Sopenharmony_ci				checkResult<VK_SUCCESS>,
1185e5c31af7Sopenharmony_ci				// Fail if pipeline is not valid
1186e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<0>
1187e5c31af7Sopenharmony_ci			}
1188e5c31af7Sopenharmony_ci		},
1189e5c31af7Sopenharmony_ci		TestParams::Iteration{
1190e5c31af7Sopenharmony_ci			// Iteration [1]: Request compilation of same pipeline without compile
1191e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NOCOMPILE,
1192e5c31af7Sopenharmony_ci			ValidatorArray{
1193e5c31af7Sopenharmony_ci				// Warn if pipeline took too long
1194e5c31af7Sopenharmony_ci				checkElapsedTime<ELAPSED_TIME_FAST, QP_TEST_RESULT_QUALITY_WARNING>
1195e5c31af7Sopenharmony_ci			}
1196e5c31af7Sopenharmony_ci		}
1197e5c31af7Sopenharmony_ci	},
1198e5c31af7Sopenharmony_ci	false
1199e5c31af7Sopenharmony_ci};
1200e5c31af7Sopenharmony_ci
1201e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1202e5c31af7Sopenharmony_ci * \brief Duplicate single pipeline recreation using derivative pipelines
1203e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1204e5c31af7Sopenharmony_cistatic constexpr TestParams DUPLICATE_SINGLE_RECREATE_DERIVATIVE =
1205e5c31af7Sopenharmony_ci{
1206e5c31af7Sopenharmony_ci	"duplicate_single_recreate_derivative",
1207e5c31af7Sopenharmony_ci	TestParams::DERIVATIVE_HANDLE,
1208e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1209e5c31af7Sopenharmony_ci		TestParams::Iteration{
1210e5c31af7Sopenharmony_ci			// Iteration [0]: Force compilation of pipeline
1211e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NORMAL,
1212e5c31af7Sopenharmony_ci			ValidatorArray{
1213e5c31af7Sopenharmony_ci				// Fail if result is not VK_SUCCESS
1214e5c31af7Sopenharmony_ci				checkResult<VK_SUCCESS>,
1215e5c31af7Sopenharmony_ci				// Fail if pipeline is not valid
1216e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<0>
1217e5c31af7Sopenharmony_ci				}
1218e5c31af7Sopenharmony_ci			},
1219e5c31af7Sopenharmony_ci		TestParams::Iteration{
1220e5c31af7Sopenharmony_ci			// Iteration [1]: Request compilation of same pipeline without compile
1221e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NOCOMPILE,
1222e5c31af7Sopenharmony_ci			ValidatorArray{
1223e5c31af7Sopenharmony_ci				// Warn if pipeline took too long
1224e5c31af7Sopenharmony_ci				checkElapsedTime<ELAPSED_TIME_FAST, QP_TEST_RESULT_QUALITY_WARNING>
1225e5c31af7Sopenharmony_ci			}
1226e5c31af7Sopenharmony_ci		}
1227e5c31af7Sopenharmony_ci	},
1228e5c31af7Sopenharmony_ci	false
1229e5c31af7Sopenharmony_ci};
1230e5c31af7Sopenharmony_ci
1231e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1232e5c31af7Sopenharmony_ci * \brief Single creation of never before seen pipeline without compile
1233e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1234e5c31af7Sopenharmony_cistatic constexpr TestParams SINGLE_PIPELINE_NO_COMPILE =
1235e5c31af7Sopenharmony_ci{
1236e5c31af7Sopenharmony_ci	"single_pipeline_no_compile",
1237e5c31af7Sopenharmony_ci	TestParams::NO_CACHE,
1238e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1239e5c31af7Sopenharmony_ci		TestParams::Iteration{
1240e5c31af7Sopenharmony_ci			TestParams::Iteration::SINGLE_NOCOMPILE,
1241e5c31af7Sopenharmony_ci			ValidatorArray{
1242e5c31af7Sopenharmony_ci				// Warn if pipeline took too long
1243e5c31af7Sopenharmony_ci				checkElapsedTime<ELAPSED_TIME_IMMEDIATE, QP_TEST_RESULT_QUALITY_WARNING>
1244e5c31af7Sopenharmony_ci			}
1245e5c31af7Sopenharmony_ci		}
1246e5c31af7Sopenharmony_ci	},
1247e5c31af7Sopenharmony_ci	false
1248e5c31af7Sopenharmony_ci};
1249e5c31af7Sopenharmony_ci
1250e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1251e5c31af7Sopenharmony_ci * \brief Batch creation of duplicate pipelines with explicit caching
1252e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1253e5c31af7Sopenharmony_cistatic constexpr TestParams DUPLICATE_BATCH_PIPELINES_EXPLICIT_CACHE =
1254e5c31af7Sopenharmony_ci{
1255e5c31af7Sopenharmony_ci	"duplicate_batch_pipelines_explicit_cache",
1256e5c31af7Sopenharmony_ci	TestParams::EXPLICIT_CACHE,
1257e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1258e5c31af7Sopenharmony_ci		TestParams::Iteration{
1259e5c31af7Sopenharmony_ci			TestParams::Iteration::BATCH_NOCOMPILE_COMPILE_NOCOMPILE,
1260e5c31af7Sopenharmony_ci			ValidatorArray{
1261e5c31af7Sopenharmony_ci				// Fail if pipeline[1] is not valid
1262e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<1>,
1263e5c31af7Sopenharmony_ci				// Warn if result is not VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT
1264e5c31af7Sopenharmony_ci				checkResult<VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1265e5c31af7Sopenharmony_ci				// Warn if pipelines[0] is not VK_NULL_HANDLE
1266e5c31af7Sopenharmony_ci				checkPipelineMustBeNull<0, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1267e5c31af7Sopenharmony_ci				// Warn if pipelines[2] is not valid
1268e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<2, QP_TEST_RESULT_COMPATIBILITY_WARNING>
1269e5c31af7Sopenharmony_ci			}
1270e5c31af7Sopenharmony_ci		}
1271e5c31af7Sopenharmony_ci	},
1272e5c31af7Sopenharmony_ci	false
1273e5c31af7Sopenharmony_ci};
1274e5c31af7Sopenharmony_ci
1275e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1276e5c31af7Sopenharmony_ci * \brief Batch creation of duplicate pipelines with no caching
1277e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1278e5c31af7Sopenharmony_cistatic constexpr TestParams DUPLICATE_BATCH_PIPELINES_NO_CACHE =
1279e5c31af7Sopenharmony_ci{
1280e5c31af7Sopenharmony_ci	"duplicate_batch_pipelines_no_cache",
1281e5c31af7Sopenharmony_ci	TestParams::NO_CACHE,
1282e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1283e5c31af7Sopenharmony_ci		TestParams::Iteration{
1284e5c31af7Sopenharmony_ci			TestParams::Iteration::BATCH_NOCOMPILE_COMPILE_NOCOMPILE,
1285e5c31af7Sopenharmony_ci			ValidatorArray{
1286e5c31af7Sopenharmony_ci				// Fail if pipeline[1] is not valid
1287e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<1>,
1288e5c31af7Sopenharmony_ci				// Warn if result is not VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT
1289e5c31af7Sopenharmony_ci				checkResult<VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1290e5c31af7Sopenharmony_ci				// Warn if pipelines[0] is not VK_NULL_HANDLE
1291e5c31af7Sopenharmony_ci				checkPipelineMustBeNull<0, QP_TEST_RESULT_COMPATIBILITY_WARNING>
1292e5c31af7Sopenharmony_ci			}
1293e5c31af7Sopenharmony_ci		}
1294e5c31af7Sopenharmony_ci	},
1295e5c31af7Sopenharmony_ci	false
1296e5c31af7Sopenharmony_ci};
1297e5c31af7Sopenharmony_ci
1298e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1299e5c31af7Sopenharmony_ci * \brief Batch creation of duplicate pipelines with derivative pipeline index
1300e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1301e5c31af7Sopenharmony_cistatic constexpr TestParams DUPLICATE_BATCH_PIPELINES_DERIVATIVE_INDEX =
1302e5c31af7Sopenharmony_ci{
1303e5c31af7Sopenharmony_ci	"duplicate_batch_pipelines_derivative_index",
1304e5c31af7Sopenharmony_ci	TestParams::DERIVATIVE_INDEX,
1305e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1306e5c31af7Sopenharmony_ci		TestParams::Iteration{
1307e5c31af7Sopenharmony_ci			TestParams::Iteration::BATCH_NOCOMPILE_COMPILE_NOCOMPILE,
1308e5c31af7Sopenharmony_ci			ValidatorArray{
1309e5c31af7Sopenharmony_ci				// Fail if pipeline[1] is not valid
1310e5c31af7Sopenharmony_ci				checkPipelineMustBeValid<1>,
1311e5c31af7Sopenharmony_ci				// Warn if result is not VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT
1312e5c31af7Sopenharmony_ci				checkResult<VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1313e5c31af7Sopenharmony_ci				// Warn if pipelines[0] is not VK_NULL_HANDLE
1314e5c31af7Sopenharmony_ci				checkPipelineMustBeNull<0, QP_TEST_RESULT_COMPATIBILITY_WARNING>
1315e5c31af7Sopenharmony_ci			}
1316e5c31af7Sopenharmony_ci		}
1317e5c31af7Sopenharmony_ci	},
1318e5c31af7Sopenharmony_ci	false
1319e5c31af7Sopenharmony_ci};
1320e5c31af7Sopenharmony_ci
1321e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1322e5c31af7Sopenharmony_ci * \brief Batch creation of pipelines with early return
1323e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1324e5c31af7Sopenharmony_cistatic constexpr TestParams BATCH_PIPELINES_EARLY_RETURN =
1325e5c31af7Sopenharmony_ci{
1326e5c31af7Sopenharmony_ci	"batch_pipelines_early_return",
1327e5c31af7Sopenharmony_ci	TestParams::NO_CACHE,
1328e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1329e5c31af7Sopenharmony_ci		TestParams::Iteration{
1330e5c31af7Sopenharmony_ci			TestParams::Iteration::BATCH_RETURN_COMPILE_NOCOMPILE,
1331e5c31af7Sopenharmony_ci			ValidatorArray{
1332e5c31af7Sopenharmony_ci				// fail if a valid pipeline follows the early-return failure
1333e5c31af7Sopenharmony_ci				checkPipelineNullAfterIndex<0>,
1334e5c31af7Sopenharmony_ci				// Warn if return was not immediate
1335e5c31af7Sopenharmony_ci				checkElapsedTime<ELAPSED_TIME_IMMEDIATE, QP_TEST_RESULT_QUALITY_WARNING>,
1336e5c31af7Sopenharmony_ci				// Warn if pipelines[0] is not VK_NULL_HANDLE
1337e5c31af7Sopenharmony_ci				checkPipelineMustBeNull<0, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1338e5c31af7Sopenharmony_ci				// Warn if result is not VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT
1339e5c31af7Sopenharmony_ci				checkResult<VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT, QP_TEST_RESULT_COMPATIBILITY_WARNING>
1340e5c31af7Sopenharmony_ci			}
1341e5c31af7Sopenharmony_ci		}
1342e5c31af7Sopenharmony_ci	},
1343e5c31af7Sopenharmony_ci	false
1344e5c31af7Sopenharmony_ci};
1345e5c31af7Sopenharmony_ci
1346e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1347e5c31af7Sopenharmony_ci * \brief Batch creation of pipelines with early return using VkPipelineCreateFlagBits2KHR from maintenance5
1348e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1349e5c31af7Sopenharmony_cistatic constexpr TestParams BATCH_PIPELINES_EARLY_RETURN_MAINTENANCE_5
1350e5c31af7Sopenharmony_ci{
1351e5c31af7Sopenharmony_ci	"batch_pipelines_early_return_maintenance5",
1352e5c31af7Sopenharmony_ci	TestParams::NO_CACHE,
1353e5c31af7Sopenharmony_ci	TestParams::IterationArray{
1354e5c31af7Sopenharmony_ci		TestParams::Iteration{
1355e5c31af7Sopenharmony_ci			TestParams::Iteration::BATCH_RETURN_COMPILE_NOCOMPILE,
1356e5c31af7Sopenharmony_ci			ValidatorArray{
1357e5c31af7Sopenharmony_ci				// fail if a valid pipeline follows the early-return failure
1358e5c31af7Sopenharmony_ci				checkPipelineNullAfterIndex<0>,
1359e5c31af7Sopenharmony_ci				// Warn if return was not immediate
1360e5c31af7Sopenharmony_ci				checkElapsedTime<ELAPSED_TIME_IMMEDIATE, QP_TEST_RESULT_QUALITY_WARNING>,
1361e5c31af7Sopenharmony_ci				// Warn if pipelines[0] is not VK_NULL_HANDLE
1362e5c31af7Sopenharmony_ci				checkPipelineMustBeNull<0, QP_TEST_RESULT_COMPATIBILITY_WARNING>,
1363e5c31af7Sopenharmony_ci				// Warn if result is not VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT
1364e5c31af7Sopenharmony_ci				checkResult<VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT, QP_TEST_RESULT_COMPATIBILITY_WARNING>
1365e5c31af7Sopenharmony_ci			}
1366e5c31af7Sopenharmony_ci		}
1367e5c31af7Sopenharmony_ci	},
1368e5c31af7Sopenharmony_ci	true,
1369e5c31af7Sopenharmony_ci};
1370e5c31af7Sopenharmony_ci
1371e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1372e5c31af7Sopenharmony_ci * \brief Full array of test cases
1373e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1374e5c31af7Sopenharmony_cistatic constexpr TestParams TEST_CASES[] =
1375e5c31af7Sopenharmony_ci{
1376e5c31af7Sopenharmony_ci	SINGLE_PIPELINE_NO_COMPILE,
1377e5c31af7Sopenharmony_ci	BATCH_PIPELINES_EARLY_RETURN,
1378e5c31af7Sopenharmony_ci	DUPLICATE_SINGLE_RECREATE_EXPLICIT_CACHING,
1379e5c31af7Sopenharmony_ci	DUPLICATE_SINGLE_RECREATE_NO_CACHING,
1380e5c31af7Sopenharmony_ci	DUPLICATE_SINGLE_RECREATE_DERIVATIVE,
1381e5c31af7Sopenharmony_ci	DUPLICATE_BATCH_PIPELINES_EXPLICIT_CACHE,
1382e5c31af7Sopenharmony_ci	DUPLICATE_BATCH_PIPELINES_NO_CACHE,
1383e5c31af7Sopenharmony_ci	DUPLICATE_BATCH_PIPELINES_DERIVATIVE_INDEX,
1384e5c31af7Sopenharmony_ci
1385e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
1386e5c31af7Sopenharmony_ci	BATCH_PIPELINES_EARLY_RETURN_MAINTENANCE_5,
1387e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
1388e5c31af7Sopenharmony_ci
1389e5c31af7Sopenharmony_ci};
1390e5c31af7Sopenharmony_ci
1391e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1392e5c31af7Sopenharmony_ci * \brief Variadic version of de::newMovePtr
1393e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1394e5c31af7Sopenharmony_citemplate <typename T, typename... args_t>
1395e5c31af7Sopenharmony_ciinline de::MovePtr<T> newMovePtr(args_t&&... args)
1396e5c31af7Sopenharmony_ci{
1397e5c31af7Sopenharmony_ci	return de::MovePtr<T>(new T(::std::forward<args_t>(args)...));
1398e5c31af7Sopenharmony_ci}
1399e5c31af7Sopenharmony_ci
1400e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1401e5c31af7Sopenharmony_ci * \brief Make test group consisting of graphics pipeline tests
1402e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1403e5c31af7Sopenharmony_civoid addGraphicsPipelineTests(TestCaseGroup& group)
1404e5c31af7Sopenharmony_ci{
1405e5c31af7Sopenharmony_ci	using namespace graphics_tests;
1406e5c31af7Sopenharmony_ci
1407e5c31af7Sopenharmony_ci	auto tests = newMovePtr<TestCaseGroup>(
1408e5c31af7Sopenharmony_ci		group.getTestContext(), "graphics_pipelines", "Test pipeline creation cache control with graphics pipelines");
1409e5c31af7Sopenharmony_ci
1410e5c31af7Sopenharmony_ci	for (const auto& params : TEST_CASES)
1411e5c31af7Sopenharmony_ci	{
1412e5c31af7Sopenharmony_ci		addFunctionCaseWithPrograms<const TestParams&>(
1413e5c31af7Sopenharmony_ci			tests.get(), params.name, checkSupport, initPrograms, testInstance, params);
1414e5c31af7Sopenharmony_ci	}
1415e5c31af7Sopenharmony_ci
1416e5c31af7Sopenharmony_ci	group.addChild(tests.release());
1417e5c31af7Sopenharmony_ci}
1418e5c31af7Sopenharmony_ci
1419e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1420e5c31af7Sopenharmony_ci * \brief Make test group consisting of compute pipeline tests
1421e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1422e5c31af7Sopenharmony_civoid addComputePipelineTests(TestCaseGroup& group)
1423e5c31af7Sopenharmony_ci{
1424e5c31af7Sopenharmony_ci	using namespace compute_tests;
1425e5c31af7Sopenharmony_ci
1426e5c31af7Sopenharmony_ci	auto tests = newMovePtr<TestCaseGroup>(
1427e5c31af7Sopenharmony_ci		group.getTestContext(), "compute_pipelines", "Test pipeline creation cache control with compute pipelines");
1428e5c31af7Sopenharmony_ci
1429e5c31af7Sopenharmony_ci	for (const auto& params : TEST_CASES)
1430e5c31af7Sopenharmony_ci	{
1431e5c31af7Sopenharmony_ci		addFunctionCaseWithPrograms<const TestParams&>(
1432e5c31af7Sopenharmony_ci			tests.get(), params.name, checkSupport, initPrograms, testInstance, params);
1433e5c31af7Sopenharmony_ci	}
1434e5c31af7Sopenharmony_ci
1435e5c31af7Sopenharmony_ci	group.addChild(tests.release());
1436e5c31af7Sopenharmony_ci}
1437e5c31af7Sopenharmony_ci
1438e5c31af7Sopenharmony_ci} // namespace
1439e5c31af7Sopenharmony_ci
1440e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1441e5c31af7Sopenharmony_ci * \brief Make pipeline creation cache control test group
1442e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1443e5c31af7Sopenharmony_ciTestCaseGroup* createCacheControlTests(TestContext& testCtx)
1444e5c31af7Sopenharmony_ci{
1445e5c31af7Sopenharmony_ci	auto tests = newMovePtr<TestCaseGroup>(testCtx, "creation_cache_control");
1446e5c31af7Sopenharmony_ci
1447e5c31af7Sopenharmony_ci	addGraphicsPipelineTests(*tests);
1448e5c31af7Sopenharmony_ci	addComputePipelineTests(*tests);
1449e5c31af7Sopenharmony_ci
1450e5c31af7Sopenharmony_ci	return tests.release();
1451e5c31af7Sopenharmony_ci}
1452e5c31af7Sopenharmony_ci
1453e5c31af7Sopenharmony_ci} // namespace pipeline
1454e5c31af7Sopenharmony_ci
1455e5c31af7Sopenharmony_ci} // namespace vkt
1456