• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  * Copyright (c) 2019-2020 NVIDIA Corporation
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Fragment Shading Rate tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktFragmentShadingRateTests.hpp"
26 #include "vktFragmentShadingRateBasic.hpp"
27 #include "vktFragmentShadingRatePixelConsistency.hpp"
28 #include "vktFragmentShadingRateGroupParams.hpp"
29 #include "vktAttachmentRateTests.hpp"
30 #include "vktFragmentShadingRateMiscTests.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "vktTestCaseUtil.hpp"
33 #include "vkPipelineConstructionUtil.hpp"
34 #include "tcuTestLog.hpp"
35 #include <limits>
36 
37 namespace vkt
38 {
39 namespace FragmentShadingRate
40 {
41 
42 namespace
43 {
44 
testLimits(Context & context)45 tcu::TestStatus testLimits(Context& context)
46 {
47 	bool			allChecksPassed					= true;
48 	tcu::TestLog&	log								= context.getTestContext().getLog();
49 	const auto&		features						= context.getDeviceFeatures();
50 	const auto&		properties						= context.getDeviceProperties();
51 	const auto&		vulkan12Features				= context.getDeviceVulkan12Features();
52 	const auto&		fragmentShadingRateFeatures		= context.getFragmentShadingRateFeatures();
53 	const auto&		fragmentShadingRateProperties	= context.getFragmentShadingRateProperties();
54 
55 	if (!fragmentShadingRateFeatures.pipelineFragmentShadingRate)
56 	{
57 		log << tcu::TestLog::Message << "pipelineFragmentShadingRate is not supported" << tcu::TestLog::EndMessage;
58 		allChecksPassed = false;
59 	}
60 
61 	if (context.getFragmentShadingRateProperties().primitiveFragmentShadingRateWithMultipleViewports && !context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate)
62 	{
63 		log << tcu::TestLog::Message << "primitiveFragmentShadingRateWithMultipleViewports "
64 										"limit should only be supported if primitiveFragmentShadingRate is supported" << tcu::TestLog::EndMessage;
65 		allChecksPassed = false;
66 	}
67 
68 	bool requiredFeatures = features.geometryShader || vulkan12Features.shaderOutputViewportIndex || context.isDeviceFunctionalitySupported("VK_EXT_shader_viewport_index_layer");
69 	if (context.getFragmentShadingRateProperties().primitiveFragmentShadingRateWithMultipleViewports && !requiredFeatures)
70 	{
71 		log << tcu::TestLog::Message << "primitiveFragmentShadingRateWithMultipleViewports limit should only "
72 										"be supported if at least one of the geometryShader feature, shaderOutputViewportIndex feature, "
73 										"or VK_EXT_shader_viewport_index_layer extension is supported" << tcu::TestLog::EndMessage;
74 		allChecksPassed = false;
75 	}
76 
77 	if (fragmentShadingRateProperties.layeredShadingRateAttachments && !fragmentShadingRateFeatures.attachmentFragmentShadingRate)
78 	{
79 		log << tcu::TestLog::Message << "layeredShadingRateAttachments should only be supported if attachmentFragmentShadingRate is supported" << tcu::TestLog::EndMessage;
80 		allChecksPassed = false;
81 	}
82 
83 	requiredFeatures = features.geometryShader || context.getMultiviewFeatures().multiview || vulkan12Features.shaderOutputViewportIndex ||
84 						context.isDeviceFunctionalitySupported("VK_EXT_shader_viewport_index_layer");
85 	if (fragmentShadingRateProperties.layeredShadingRateAttachments && !requiredFeatures)
86 	{
87 		log << tcu::TestLog::Message << "layeredShadingRateAttachments should only be supported if at least one of the geometryShader feature, multiview feature, "
88 										"shaderOutputViewportIndex feature, or VK_EXT_shader_viewport_index_layer extension is supported" << tcu::TestLog::EndMessage;
89 		allChecksPassed = false;
90 	}
91 
92 	requiredFeatures = fragmentShadingRateFeatures.primitiveFragmentShadingRate || fragmentShadingRateFeatures.attachmentFragmentShadingRate;
93 	if (fragmentShadingRateProperties.fragmentShadingRateNonTrivialCombinerOps && !requiredFeatures)
94 	{
95 		log << tcu::TestLog::Message << "fragmentShadingRateNonTrivialCombinerOps should only be supported if at least one of primitiveFragmentShadingRate "
96 										"or attachmentFragmentShadingRate is supported" << tcu::TestLog::EndMessage;
97 		allChecksPassed = false;
98 	}
99 
100 	if (fragmentShadingRateProperties.maxFragmentSizeAspectRatio > std::max(fragmentShadingRateProperties.maxFragmentSize.width, fragmentShadingRateProperties.maxFragmentSize.height))
101 	{
102 		log << tcu::TestLog::Message << "maxFragmentSizeAspectRatio should be less than or equal to the maximum width / height of maxFragmentSize" << tcu::TestLog::EndMessage;
103 		allChecksPassed = false;
104 	}
105 
106 	if (fragmentShadingRateProperties.maxFragmentSizeAspectRatio < 2)
107 	{
108 		log << tcu::TestLog::Message << "maxFragmentSizeAspectRatio should be at least 2" << tcu::TestLog::EndMessage;
109 		allChecksPassed = false;
110 	}
111 
112 	if (!deIntIsPow2(static_cast<int>(fragmentShadingRateProperties.maxFragmentSizeAspectRatio)))
113 	{
114 		log << tcu::TestLog::Message << "maxFragmentSizeAspectRatio should be power of 2" << tcu::TestLog::EndMessage;
115 		allChecksPassed = false;
116 	}
117 
118 	if (fragmentShadingRateProperties.fragmentShadingRateWithShaderSampleMask && (fragmentShadingRateProperties.maxFragmentShadingRateCoverageSamples > (properties.limits.maxSampleMaskWords * 32)))
119 	{
120 		log << tcu::TestLog::Message << "maxFragmentShadingRateCoverageSamples should be less than or equal maxSampleMaskWords * 32 "
121 										"if fragmentShadingRateWithShaderSampleMask is supported" << tcu::TestLog::EndMessage;
122 		allChecksPassed = false;
123 	}
124 
125 	deUint32 requiredValue = fragmentShadingRateProperties.maxFragmentSize.width * fragmentShadingRateProperties.maxFragmentSize.height *
126 								fragmentShadingRateProperties.maxFragmentShadingRateRasterizationSamples;
127 	if (fragmentShadingRateProperties.maxFragmentShadingRateCoverageSamples > requiredValue)
128 	{
129 		log << tcu::TestLog::Message << "maxFragmentShadingRateCoverageSamples should be less than or equal to the product of the width and height of "
130 										"maxFragmentSize and the samples reported by maxFragmentShadingRateRasterizationSamples" << tcu::TestLog::EndMessage;
131 		allChecksPassed = false;
132 	}
133 
134 	if (fragmentShadingRateProperties.maxFragmentShadingRateCoverageSamples < 16)
135 	{
136 		log << tcu::TestLog::Message << "maxFragmentShadingRateCoverageSamples should at least be 16" << tcu::TestLog::EndMessage;
137 		allChecksPassed = false;
138 	}
139 
140 	if (fragmentShadingRateProperties.maxFragmentShadingRateRasterizationSamples < vk::VK_SAMPLE_COUNT_4_BIT)
141 	{
142 		log << tcu::TestLog::Message << "maxFragmentShadingRateRasterizationSamples should supports at least VK_SAMPLE_COUNT_4_BIT" << tcu::TestLog::EndMessage;
143 		allChecksPassed = false;
144 	}
145 
146 	if (fragmentShadingRateProperties.fragmentShadingRateWithConservativeRasterization && !context.isDeviceFunctionalitySupported("VK_EXT_conservative_rasterization"))
147 	{
148 		log << tcu::TestLog::Message << "fragmentShadingRateWithConservativeRasterization should only be supported if VK_EXT_conservative_rasterization is supported" << tcu::TestLog::EndMessage;
149 		allChecksPassed = false;
150 	}
151 
152 	if (fragmentShadingRateProperties.fragmentShadingRateWithFragmentShaderInterlock && !context.isDeviceFunctionalitySupported("VK_EXT_fragment_shader_interlock"))
153 	{
154 		log << tcu::TestLog::Message << "fragmentShadingRateWithFragmentShaderInterlock should only be supported if VK_EXT_fragment_shader_interlock is supported" << tcu::TestLog::EndMessage;
155 		allChecksPassed = false;
156 	}
157 
158 	if (fragmentShadingRateProperties.fragmentShadingRateWithCustomSampleLocations && !context.isDeviceFunctionalitySupported("VK_EXT_sample_locations"))
159 	{
160 		log << tcu::TestLog::Message << "fragmentShadingRateWithCustomSampleLocations should only be supported if VK_EXT_sample_locations is supported" << tcu::TestLog::EndMessage;
161 		allChecksPassed = false;
162 	}
163 
164 	if (fragmentShadingRateFeatures.attachmentFragmentShadingRate)
165 	{
166 		if ((fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.width < 8) ||
167 			(fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.height < 8))
168 		{
169 			log << tcu::TestLog::Message << "maxFragmentShadingRateAttachmentTexelSize should at least be { 8,8 }" << tcu::TestLog::EndMessage;
170 			allChecksPassed = false;
171 		}
172 
173 		if ((fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.width > 32) ||
174 			(fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.height > 32))
175 		{
176 			log << tcu::TestLog::Message << "minFragmentShadingRateAttachmentTexelSize should't be greater than { 32,32 }" << tcu::TestLog::EndMessage;
177 			allChecksPassed = false;
178 		}
179 
180 		if ((fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.width < fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.width) ||
181 			(fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.height < fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.height))
182 		{
183 			log << tcu::TestLog::Message << "maxFragmentShadingRateAttachmentTexelSize should be greater than or equal to "
184 				"minFragmentShadingRateAttachmentTexelSize in each dimension" << tcu::TestLog::EndMessage;
185 			allChecksPassed = false;
186 		}
187 
188 		if (!deIntIsPow2(static_cast<int>(fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.width)) ||
189 			!deIntIsPow2(static_cast<int>(fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.height)))
190 		{
191 			log << tcu::TestLog::Message << "maxFragmentShadingRateAttachmentTexelSize should be power of 2" << tcu::TestLog::EndMessage;
192 			allChecksPassed = false;
193 		}
194 
195 		if (!deIntIsPow2(static_cast<int>(fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.width)) ||
196 			!deIntIsPow2(static_cast<int>(fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.height)))
197 		{
198 			log << tcu::TestLog::Message << "minFragmentShadingRateAttachmentTexelSize should be power of 2" << tcu::TestLog::EndMessage;
199 			allChecksPassed = false;
200 		}
201 	}
202 	else
203 	{
204 		if ((fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.width != 0) ||
205 			(fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.height != 0))
206 		{
207 			log << tcu::TestLog::Message << "maxFragmentShadingRateAttachmentTexelSize should be { 0,0 } when "
208 											"attachmentFragmentShadingRate is not supported" << tcu::TestLog::EndMessage;
209 			allChecksPassed = false;
210 		}
211 
212 		if ((fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.width != 0) ||
213 			(fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.height != 0))
214 		{
215 			log << tcu::TestLog::Message << "minFragmentShadingRateAttachmentTexelSize should be { 0,0 } when "
216 											"attachmentFragmentShadingRate is not supported" << tcu::TestLog::EndMessage;
217 			allChecksPassed = false;
218 		}
219 	}
220 
221 	if ((fragmentShadingRateProperties.maxFragmentSize.width < 2) ||
222 		(fragmentShadingRateProperties.maxFragmentSize.height < 2))
223 	{
224 		log << tcu::TestLog::Message << "maxFragmentSize should at least be { 2,2 }" << tcu::TestLog::EndMessage;
225 		allChecksPassed = false;
226 	}
227 
228 	if ((fragmentShadingRateProperties.maxFragmentSize.width > 4) ||
229 		(fragmentShadingRateProperties.maxFragmentSize.height > 4))
230 	{
231 		log << tcu::TestLog::Message << "maxFragmentSize should't be greater than{ 4,4 }" << tcu::TestLog::EndMessage;
232 		allChecksPassed = false;
233 	}
234 
235 	if (allChecksPassed)
236 		return tcu::TestStatus::pass("pass");
237 	return tcu::TestStatus::fail("fail");
238 }
239 
testShadingRates(Context & context)240 tcu::TestStatus testShadingRates(Context& context)
241 {
242 	bool							someChecksFailed					= false;
243 	tcu::TestLog&					log									= context.getTestContext().getLog();
244 	const vk::InstanceInterface&	vki									= context.getInstanceInterface();
245 	vk::VkPhysicalDevice			physicalDevice						= context.getPhysicalDevice();
246 	const auto&						fragmentShadingRateProperties		= context.getFragmentShadingRateProperties();
247 	deUint32						supportedFragmentShadingRateCount	= 0;
248 
249 	vk::VkResult result = vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL);
250 	if ((result != vk::VK_SUCCESS) && (result != vk::VK_ERROR_OUT_OF_HOST_MEMORY))
251 	{
252 		someChecksFailed = true;
253 		log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned invalid result" << tcu::TestLog::EndMessage;
254 	}
255 
256 	std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> fragmentShadingRateVect(supportedFragmentShadingRateCount);
257 	for (auto& fragmentShadingRate : fragmentShadingRateVect)
258 	{
259 		fragmentShadingRate.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
260 		fragmentShadingRate.pNext = DE_NULL;
261 	}
262 
263 	// Pass a value of 1 into pFragmentShadingRateCount, and an array of at least length one into pFragmentShadingRates.
264 	// Check that the returned value is either VK_INCOMPLETE or VK_ERROR_OUT_OF_HOST_MEMORY(and issue a quality warning in the latter case).
265 	supportedFragmentShadingRateCount = 1u;
266 	result = vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, fragmentShadingRateVect.data());
267 	if ((result != vk::VK_INCOMPLETE) && (result != vk::VK_ERROR_OUT_OF_HOST_MEMORY))
268 	{
269 		someChecksFailed = true;
270 		log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned invalid result" << tcu::TestLog::EndMessage;
271 	}
272 
273 	// Get all available fragment shading rates
274 	supportedFragmentShadingRateCount = static_cast<deUint32>(fragmentShadingRateVect.size());
275 	result = vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, fragmentShadingRateVect.data());
276 	if ((result != vk::VK_SUCCESS) && (result != vk::VK_ERROR_OUT_OF_HOST_MEMORY))
277 	{
278 		someChecksFailed = true;
279 		log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned invalid result" << tcu::TestLog::EndMessage;
280 	}
281 
282 	bool		widthCheckPassed	= true;
283 	bool		heightCheckPassed	= true;
284 	deUint32	previousWidth		= std::numeric_limits<deUint32>::max();
285 	deUint32	previousHeight		= std::numeric_limits<deUint32>::max();
286 
287 	for (const auto& fsr : fragmentShadingRateVect)
288 	{
289 		const auto& fragmentSize = fsr.fragmentSize;
290 
291 		// Check that rate width and height are power-of-two
292 		if (!deIntIsPow2(static_cast<int>(fragmentSize.width)) ||
293 			!deIntIsPow2(static_cast<int>(fragmentSize.height)))
294 		{
295 			log << tcu::TestLog::Message << "fragmentSize should be power of 2" << tcu::TestLog::EndMessage;
296 			someChecksFailed = true;
297 		}
298 
299 		// Check that the width and height are less than the values in the maxFragmentSize limit
300 		if ((fragmentSize.width > fragmentShadingRateProperties.maxFragmentSize.width) ||
301 			(fragmentSize.height > fragmentShadingRateProperties.maxFragmentSize.height))
302 		{
303 			log << tcu::TestLog::Message << "fragmentSize width and height are not less than the values in the maxFragmentSize" << tcu::TestLog::EndMessage;
304 			someChecksFailed = true;
305 		}
306 
307 		if ((fragmentSize.width * fragmentSize.height) == 1)
308 		{
309 			// special case for fragmentSize {1, 1}
310 			if (fsr.sampleCounts != ~0u)
311 			{
312 				log << tcu::TestLog::Message << "implementations must support sampleCounts equal to ~0 for fragmentSize {1, 1}" << tcu::TestLog::EndMessage;
313 				someChecksFailed = true;
314 			}
315 		}
316 		else
317 		{
318 			// get highest sample count value
319 			deUint32 highestSampleCount = 0x80000000;
320 			while (highestSampleCount)
321 			{
322 				if (fsr.sampleCounts & highestSampleCount)
323 					break;
324 				highestSampleCount >>= 1;
325 			}
326 
327 			// Check that the highest sample count in sampleCounts is less than or equal to maxFragmentShadingRateRasterizationSamples limit
328 			if (highestSampleCount > static_cast<deUint32>(fragmentShadingRateProperties.maxFragmentShadingRateRasterizationSamples))
329 			{
330 				log << tcu::TestLog::Message << "highest sample count value is not less than or equal to the maxFragmentShadingRateRasterizationSamples limit" << tcu::TestLog::EndMessage;
331 				someChecksFailed = true;
332 			}
333 
334 			// Check that the product of the width, height, and highest sample count value is less than the maxFragmentShadingRateCoverageSamples limit
335 			if ((fragmentSize.width * fragmentSize.height * highestSampleCount) > fragmentShadingRateProperties.maxFragmentShadingRateCoverageSamples)
336 			{
337 				log << tcu::TestLog::Message << "product of the width, height, and highest sample count value is not less than the maxFragmentShadingRateCoverageSamples limit" << tcu::TestLog::EndMessage;
338 				someChecksFailed = true;
339 			}
340 		}
341 
342 		// Check that the entries in the array are ordered first by largest to smallest width, then largest to smallest height
343 		{
344 			const deUint32 currentWidth = fragmentSize.width;
345 			if (widthCheckPassed && (currentWidth > previousWidth))
346 			{
347 				log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned entries that are not ordered by largest to smallest width" << tcu::TestLog::EndMessage;
348 				widthCheckPassed = false;
349 			}
350 
351 			deUint32 currentHeight = fragmentSize.height;
352 			if (heightCheckPassed)
353 			{
354 				// we can check order of height only for entries that have same width
355 				if (currentWidth == previousWidth)
356 				{
357 					if (currentHeight > previousHeight)
358 					{
359 						log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned entries with same width but height is not ordered by largest to smallest" << tcu::TestLog::EndMessage;
360 						heightCheckPassed = false;
361 					}
362 				}
363 				else
364 					currentHeight = std::numeric_limits<deUint32>::max();
365 			}
366 
367 			previousWidth = currentWidth;
368 			previousHeight = currentHeight;
369 		}
370 
371 		// Check that no two entries in the array have the same fragmentSize.width and fragmentSize.height value
372 		{
373 			deUint32 count = 0;
374 			for (const auto& fsrB : fragmentShadingRateVect)
375 			{
376 				if ((fragmentSize.width  == fsrB.fragmentSize.width) &&
377 					(fragmentSize.height == fsrB.fragmentSize.height))
378 				{
379 					if (++count > 1)
380 					{
381 						log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned entries with same fragmentSize" << tcu::TestLog::EndMessage;
382 						someChecksFailed = true;
383 						break;
384 					}
385 				}
386 			}
387 		}
388 
389 		// Check that 1x1, 1x2, 2x1, and 2x2 rates are supported with sample counts of 1 and 4
390 		if ((fragmentSize.width < 3) && (fragmentSize.height < 3) &&
391 			(!(fsr.sampleCounts & vk::VK_SAMPLE_COUNT_1_BIT) || !(fsr.sampleCounts & vk::VK_SAMPLE_COUNT_4_BIT)))
392 		{
393 			log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned 1x1, 1x2, 2x1, and 2x2 rates with sample counts not supporting 1 and 4" << tcu::TestLog::EndMessage;
394 			someChecksFailed = true;
395 		}
396 
397 		// If the framebufferColorSampleCounts limit includes a sample count of 2, ensure that a sample count of 2 is also reported for the 1x1, 1x2, 2x1, and 2x2 rates.
398 		if (context.getDeviceProperties().limits.framebufferColorSampleCounts & vk::VK_SAMPLE_COUNT_2_BIT)
399 		{
400 			if ((fragmentSize.width < 3) && (fragmentSize.height < 3) &&
401 				!(fsr.sampleCounts & vk::VK_SAMPLE_COUNT_2_BIT))
402 			{
403 				log << tcu::TestLog::Message << "vkGetPhysicalDeviceFragmentShadingRatesKHR returned 1x1, 1x2, 2x1, and 2x2 rates with sample counts not supporting 2 while framebufferColorSampleCounts does" << tcu::TestLog::EndMessage;
404 				someChecksFailed = true;
405 			}
406 		}
407 	}
408 
409 	if (someChecksFailed || !widthCheckPassed || !heightCheckPassed)
410 		return tcu::TestStatus::fail("fail");
411 
412 	return tcu::TestStatus::pass("pass");
413 }
414 
checkSupport(Context & context)415 void checkSupport(Context& context)
416 {
417 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
418 }
419 
createMiscTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)420 void createMiscTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
421 {
422 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc"));
423 
424 	addFunctionCase(group.get(), "limits", checkSupport, testLimits);
425 	addFunctionCase(group.get(), "shading_rates", checkSupport, testShadingRates);
426 
427 	createFragmentShadingRateMiscTests(group.get());
428 
429 	parentGroup->addChild(group.release());
430 }
431 
createTests(tcu::TestCaseGroup * group,SharedGroupParams groupParams)432 void createTests (tcu::TestCaseGroup* group, SharedGroupParams groupParams)
433 {
434 	tcu::TestContext& testCtx = group->getTestContext();
435 
436 	createBasicTests(testCtx, group, groupParams);
437 
438 	// attachmentFragmentShadingRate feature is tested with basic tests so there is no need to
439 	// duplicating those tests for secondary command buffer;
440 	// those tests are also not repeated for non monolithic pipelines
441 	if (!groupParams->useSecondaryCmdBuffer && (groupParams->pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC))
442 		createAttachmentRateTests(testCtx, group, groupParams);
443 
444 	// run pixel consistency tests and misc tests only with renderpass2 and monolithic pipeline
445 	if (!groupParams->useDynamicRendering && !groupParams->useSecondaryCmdBuffer && (groupParams->pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC))
446 	{
447 		// there is no point in duplicating those tests for dynamic rendering
448 		createMiscTests(testCtx, group);
449 
450 		// subpasses can't be translated to dynamic rendering
451 		createPixelConsistencyTests(testCtx, group);
452 	}
453 }
454 
createPipelineConstructionTypePermutations(tcu::TestCaseGroup * parentGroup,SharedGroupParams baseGroupParams)455 void createPipelineConstructionTypePermutations(tcu::TestCaseGroup* parentGroup, SharedGroupParams baseGroupParams)
456 {
457 	tcu::TestContext& testCtx = parentGroup->getTestContext();
458 
459 	auto constructGroupParams = [&baseGroupParams](vk::PipelineConstructionType pipelineConstructionType)
460 	{
461 		return SharedGroupParams(new GroupParams
462 		{
463 			baseGroupParams->useDynamicRendering,
464 			baseGroupParams->useSecondaryCmdBuffer,
465 			baseGroupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass,
466 			pipelineConstructionType,
467 		});
468 	};
469 
470 	typedef de::MovePtr<tcu::TestCaseGroup> TestGroupPtr;
471 	// Monolithic pipeline tests
472 	TestGroupPtr monolithic			(createTestGroup(testCtx, "monolithic", createTests, constructGroupParams(vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)));
473 	parentGroup->addChild(monolithic.release());
474 
475 #ifndef CTS_USES_VULKANSC
476 	// Graphics pipeline library tests
477 	TestGroupPtr pipelineLibrary	(createTestGroup(testCtx, "pipeline_library", createTests, constructGroupParams(vk::PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)));
478 	// Fast linked graphics pipeline library tests
479 	TestGroupPtr fastLinkedLibrary	(createTestGroup(testCtx, "fast_linked_library", createTests, constructGroupParams(vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY)));
480 
481 	parentGroup->addChild(pipelineLibrary.release());
482 	parentGroup->addChild(fastLinkedLibrary.release());
483 #endif // CTS_USES_VULKANSC
484 }
485 
486 #ifndef CTS_USES_VULKANSC
createDynamicRenderingPermutations(tcu::TestCaseGroup * parentGroup)487 void createDynamicRenderingPermutations(tcu::TestCaseGroup* parentGroup)
488 {
489 	tcu::TestContext& testCtx = parentGroup->getTestContext();
490 
491 	auto constructGroupParams = [](bool useSecondaryCmdBuffer, bool secondaryCmdBufferCompletelyContainsDynamicRenderpass)
492 	{
493 		return SharedGroupParams(new GroupParams
494 			{
495 				true,														// bool							useDynamicRendering;
496 				useSecondaryCmdBuffer,										// bool							useSecondaryCmdBuffer;
497 				secondaryCmdBufferCompletelyContainsDynamicRenderpass,		// bool							secondaryCmdBufferCompletelyContainsDynamicRenderpass;
498 				vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC,					// PipelineConstructionType		pipelineConstructionType;
499 			});
500 	};
501 
502 	typedef de::MovePtr<tcu::TestCaseGroup> TestGroupPtr;
503 	// Draw using Draw commands are recorded in primary command buffer
504 	TestGroupPtr drPrimaryCmdBuffGroup			(createTestGroup(testCtx, "primary_cmd_buff", createPipelineConstructionTypePermutations, constructGroupParams(false, false)));
505 	// Secondary command buffer doesn't include begin/endRendering
506 	TestGroupPtr drPartialSecondaryCmdBuffGroup	(createTestGroup(testCtx, "partial_secondary_cmd_buff", createTests, constructGroupParams(true, false)));
507 	// Secondary command buffer contains completely dynamic renderpass
508 	TestGroupPtr drCompleteSecondaryCmdBuffGroup(createTestGroup(testCtx, "complete_secondary_cmd_buff", createTests, constructGroupParams(true, true)));
509 
510 	parentGroup->addChild(drPrimaryCmdBuffGroup.release());
511 	parentGroup->addChild(drPartialSecondaryCmdBuffGroup.release());
512 	parentGroup->addChild(drCompleteSecondaryCmdBuffGroup.release());
513 }
514 #endif // CTS_USES_VULKANSC
515 
516 } // anonymous
517 
createTests(tcu::TestContext & testCtx,const std::string & name)518 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx, const std::string& name)
519 {
520 	// Fragment shading rate tests
521 	de::MovePtr<tcu::TestCaseGroup> mainGroup			(new tcu::TestCaseGroup(testCtx, name.c_str()));
522 	// Draw using render pass object
523 	de::MovePtr<tcu::TestCaseGroup> renderpass2Group	(createTestGroup(testCtx, "renderpass2",
524 		createPipelineConstructionTypePermutations,
525 		SharedGroupParams(new GroupParams
526 		{
527 			false,																// bool							useDynamicRendering;
528 			false,																// bool							useSecondaryCmdBuffer;
529 			false,																// bool							secondaryCmdBufferCompletelyContainsDynamicRenderpass;
530 			vk::PipelineConstructionType(0)		// placeholder					// PipelineConstructionType		pipelineConstructionType;
531 		})));
532 	mainGroup->addChild(renderpass2Group.release());
533 
534 #ifndef CTS_USES_VULKANSC
535 	de::MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup(createTestGroup(testCtx, "dynamic_rendering", createDynamicRenderingPermutations));
536 	mainGroup->addChild(dynamicRenderingGroup.release());
537 #endif // CTS_USES_VULKANSC
538 
539 	return mainGroup.release();
540 }
541 
542 } // FragmentShadingRate
543 } // vkt
544