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