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