1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group Inc.
6  * Copyright (c) 2018-2020 NVIDIA Corporation
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Tests for VK_KHR_fragment_shading_rate
25  * The test renders 9*9 triangles, where each triangle has one of the valid
26  * fragment sizes ({1,2,4},{1,2,4}) (clamped to implementation limits) for
27  * each of the pipeline shading rate and the primitive shading rate. The
28  * fragment shader does an atomic add to a memory location to get a unique
29  * identifier for the fragment, and outputs the primitive ID, atomic counter,
30  * fragment size, and some other info the the color output. Then a compute
31  * shader copies this to buffer memory, and the host verifies several
32  * properties of the output. For example, if a sample has a particular
33  * primitive ID and atomic value, then all other samples in the tile with
34  * the same primitive ID should have the same atomic value.
35  *//*--------------------------------------------------------------------*/
36 
37 #include "vktFragmentShadingRateBasic.hpp"
38 
39 #include "vkBufferWithMemory.hpp"
40 #include "vkImageWithMemory.hpp"
41 #include "vkQueryUtil.hpp"
42 #include "vkBuilderUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkTypeUtil.hpp"
45 #include "vkObjUtil.hpp"
46 #include "vkImageUtil.hpp"
47 #include "vkStrUtil.hpp"
48 #include "vkBarrierUtil.hpp"
49 
50 #include "vktTestGroupUtil.hpp"
51 #include "vktTestCase.hpp"
52 
53 #include "deDefs.h"
54 #include "deMath.h"
55 #include "deRandom.h"
56 #include "deSharedPtr.hpp"
57 #include "deString.h"
58 
59 #include "tcuTestCase.hpp"
60 #include "tcuTestLog.hpp"
61 #include "tcuImageCompare.hpp"
62 
63 #include <set>
64 #include <string>
65 #include <sstream>
66 #include <vector>
67 #include <algorithm>
68 #include <iterator>
69 
70 namespace vkt
71 {
72 namespace FragmentShadingRate
73 {
74 namespace
75 {
76 using namespace vk;
77 using namespace std;
78 
79 #define NUM_TRIANGLES (9 * 9)
80 
81 enum class AttachmentUsage
82 {
83     NO_ATTACHMENT = 0,
84     NO_ATTACHMENT_PTR,
85     WITH_ATTACHMENT,
86     WITH_ATTACHMENT_WITHOUT_IMAGEVIEW, // No imageview at VkRenderingFragmentShadingRateAttachmentInfoKHR.
87 };
88 
89 struct CaseDef
90 {
91     SharedGroupParams groupParams;
92     int32_t seed;
93     VkExtent2D framebufferDim;
94     VkSampleCountFlagBits samples;
95     VkFragmentShadingRateCombinerOpKHR combinerOp[2];
96     AttachmentUsage attachmentUsage;
97     bool shaderWritesRate;
98     bool geometryShader;
99     bool meshShader;
100     bool useDynamicState;
101     bool useApiSampleMask;
102     bool useSampleMaskIn;
103     bool conservativeEnable;
104     VkConservativeRasterizationModeEXT conservativeMode;
105     bool useDepthStencil; // == fragDepth || fragStencil
106     bool fragDepth;
107     bool fragStencil;
108     bool multiViewport;
109     bool colorLayered;
110     bool srLayered; // colorLayered must also be true
111     uint32_t numColorLayers;
112     bool multiView;
113     bool correlationMask;
114     bool interlock;
115     bool sampleLocations;
116     bool sampleShadingEnable;
117     bool sampleShadingInput;
118     bool sampleMaskTest;
119     bool earlyAndLateTest;
120     bool garbageAttachment;
121     bool dsClearOp;
122     uint32_t dsBaseMipLevel;
123     bool multiSubpasses;
124     bool maintenance6;
125 
useAttachmentvkt::FragmentShadingRate::__anonc5b06d950111::CaseDef126     bool useAttachment() const
127     {
128         return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT);
129     }
130 
useAttachmentWithoutImageViewvkt::FragmentShadingRate::__anonc5b06d950111::CaseDef131     bool useAttachmentWithoutImageView() const
132     {
133         return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW);
134     }
135 };
136 
137 class FSRTestInstance : public TestInstance
138 {
139 public:
140     FSRTestInstance(Context &context, const CaseDef &data);
141     ~FSRTestInstance(void);
142     tcu::TestStatus iterate(void);
143 
144 private:
145     // Test parameters
146     CaseDef m_data;
147 
148     // Cache simulated combiner operations, to avoid recomputing per-sample
149     int32_t m_simulateValueCount;
150     vector<int32_t> m_simulateCache;
151     // Cache mapping of primitive ID to pipeline/primitive shading rate
152     vector<int32_t> m_primIDToPrimitiveShadingRate;
153     vector<int32_t> m_primIDToPipelineShadingRate;
154     uint32_t m_supportedFragmentShadingRateCount;
155     vector<VkPhysicalDeviceFragmentShadingRateKHR> m_supportedFragmentShadingRates;
156     VkPhysicalDeviceFragmentShadingRatePropertiesKHR m_shadingRateProperties;
157 #ifndef CTS_USES_VULKANSC
158     VkPhysicalDeviceMaintenance6PropertiesKHR m_maintenance6Properties;
159 #endif
160 
161 protected:
162     void preRenderCommands(VkCommandBuffer cmdBuffer, ImageWithMemory *cbImage, ImageWithMemory *dsImage,
163                            ImageWithMemory *secCbImage, ImageWithMemory *derivImage, uint32_t derivNumLevels,
164                            ImageWithMemory *srImage, VkImageLayout srLayout, BufferWithMemory *srFillBuffer,
165                            uint32_t numSRLayers, uint32_t srWidth, uint32_t srHeight, uint32_t srFillBpp,
166                            const VkClearValue &clearColor, const VkClearValue &clearDepthStencil);
167     void beginLegacyRender(VkCommandBuffer cmdBuffer, RenderPassWrapper &renderPass, VkImageView srImageView,
168                            VkImageView cbImageView, VkImageView dsImageView, VkImageView secCbImageView,
169                            bool imagelessFB) const;
170     void drawCommands(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
171                       const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
172                       const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
173                       const VkPipelineVertexInputStateCreateInfo *vertexInputState,
174                       const VkPipelineDynamicStateCreateInfo *dynamicState,
175                       const VkPipelineRasterizationStateCreateInfo *rasterizationState,
176                       const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
177                       const VkPipelineMultisampleStateCreateInfo *multisampleState,
178                       VkPipelineFragmentShadingRateStateCreateInfoKHR *shadingRateState,
179                       PipelineRenderingCreateInfoWrapper dynamicRenderingState, const ShaderWrapper vertShader,
180                       const ShaderWrapper geomShader, const ShaderWrapper meshShader, const ShaderWrapper fragShader,
181                       const std::vector<VkDescriptorSet> &descriptorSet, VkBuffer vertexBuffer,
182                       const uint32_t pushConstantSize);
183 
184     void copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer, const ImageWithMemory *image,
185                                           const BufferWithMemory *outputBuffer, const VkDeviceSize bufferSize);
186 
187     void drawCommandsOnNormalSubpass(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
188                                      const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
189                                      const PipelineLayoutWrapper &pipelineLayout, const RenderPassWrapper &renderPass,
190                                      const VkPipelineRasterizationStateCreateInfo *rasterizationState,
191                                      const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
192                                      const VkPipelineMultisampleStateCreateInfo *multisampleState,
193                                      const ShaderWrapper &vertShader, const ShaderWrapper &fragShader,
194                                      const uint32_t subpass, VkBuffer vertexBuffer);
195 
196 #ifndef CTS_USES_VULKANSC
197     void beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat cbFormat, VkFormat dsFormat,
198                                  VkRenderingFlagsKHR renderingFlags = 0u) const;
199     void beginDynamicRender(VkCommandBuffer cmdBuffer, VkImageView srImageView, VkImageLayout srImageLayout,
200                             const VkExtent2D &srTexelSize, VkImageView cbImageView, VkImageView dsImageView,
201                             const VkClearValue &clearColor, const VkClearValue &clearDepthStencil,
202                             VkRenderingFlagsKHR renderingFlags = 0u) const;
203 #endif // CTS_USES_VULKANSC
204 
205     int32_t PrimIDToPrimitiveShadingRate(int32_t primID);
206     int32_t PrimIDToPipelineShadingRate(int32_t primID);
207     VkExtent2D SanitizeExtent(VkExtent2D ext) const;
208     int32_t SanitizeRate(int32_t rate) const;
209     int32_t ShadingRateExtentToClampedMask(VkExtent2D ext) const;
210     int32_t ShadingRateExtentToEnum(VkExtent2D ext) const;
211     VkExtent2D ShadingRateEnumToExtent(int32_t rate) const;
212     int32_t Simulate(int32_t rate0, int32_t rate1, int32_t rate2);
213     VkExtent2D Combine(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const;
214     int32_t CombineMasks(int32_t rateMask0, int32_t rateMask1, VkFragmentShadingRateCombinerOpKHR comb,
215                          bool allowUnclampedResult) const;
216     bool Force1x1() const;
217 };
218 
FSRTestInstance(Context & context,const CaseDef & data)219 FSRTestInstance::FSRTestInstance(Context &context, const CaseDef &data)
220     : vkt::TestInstance(context)
221     , m_data(data)
222     , m_simulateValueCount(((4 * 4) | 4) + 1)
223     , m_simulateCache(m_simulateValueCount * m_simulateValueCount * m_simulateValueCount, ~0)
224     , m_primIDToPrimitiveShadingRate(NUM_TRIANGLES, ~0)
225     , m_primIDToPipelineShadingRate(NUM_TRIANGLES, ~0)
226 {
227     m_supportedFragmentShadingRateCount = 0;
228     m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(
229         m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, DE_NULL);
230 
231     if (m_supportedFragmentShadingRateCount < 3)
232         TCU_THROW(TestError, "*pFragmentShadingRateCount too small");
233 
234     m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount);
235     for (uint32_t i = 0; i < m_supportedFragmentShadingRateCount; ++i)
236     {
237         m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
238         m_supportedFragmentShadingRates[i].pNext = nullptr;
239     }
240     m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(
241         m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]);
242 
243     m_shadingRateProperties = m_context.getFragmentShadingRateProperties();
244 #ifndef CTS_USES_VULKANSC
245     m_maintenance6Properties = m_context.getMaintenance6Properties();
246 #endif
247 }
248 
~FSRTestInstance(void)249 FSRTestInstance::~FSRTestInstance(void)
250 {
251 }
252 
253 class FSRTestCase : public TestCase
254 {
255 public:
256     FSRTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
257     ~FSRTestCase(void);
258     virtual void initPrograms(SourceCollections &programCollection) const;
259     virtual TestInstance *createInstance(Context &context) const;
260     virtual void checkSupport(Context &context) const;
261 
262 private:
263     CaseDef m_data;
264 };
265 
FSRTestCase(tcu::TestContext & context,const char * name,const CaseDef data)266 FSRTestCase::FSRTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
267     : vkt::TestCase(context, name)
268     , m_data(data)
269 {
270 }
271 
~FSRTestCase(void)272 FSRTestCase::~FSRTestCase(void)
273 {
274 }
275 
Force1x1() const276 bool FSRTestInstance::Force1x1() const
277 {
278     if (m_data.useApiSampleMask && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
279         return true;
280 
281     if (m_data.useSampleMaskIn && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderSampleMask)
282         return true;
283 
284     if (m_data.conservativeEnable &&
285         !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithConservativeRasterization)
286         return true;
287 
288     if (m_data.useDepthStencil &&
289         !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderDepthStencilWrites)
290         return true;
291 
292     if (m_data.interlock &&
293         !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithFragmentShaderInterlock)
294         return true;
295 
296     if (m_data.sampleLocations &&
297         !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithCustomSampleLocations)
298         return true;
299 
300     if (m_data.sampleShadingEnable || m_data.sampleShadingInput)
301         return true;
302 
303     return false;
304 }
305 
306 static VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
307                                    VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
308 
309 static VkImageUsageFlags dsUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
310                                    VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
311 
checkSupport(Context & context) const312 void FSRTestCase::checkSupport(Context &context) const
313 {
314     context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
315 
316     if (m_data.groupParams->useDynamicRendering)
317         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
318 
319     if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
320         TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
321 
322     if (m_data.shaderWritesRate && !context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate)
323         TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
324 
325     if (!context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate &&
326         m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
327         TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
328 
329     if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
330         m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
331         TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
332 
333     const auto &vki    = context.getInstanceInterface();
334     const auto physDev = context.getPhysicalDevice();
335 
336     VkImageFormatProperties imageProperties;
337     VkResult result = vki.getPhysicalDeviceImageFormatProperties(physDev, VK_FORMAT_R32G32B32A32_UINT, VK_IMAGE_TYPE_2D,
338                                                                  VK_IMAGE_TILING_OPTIMAL, cbUsage, 0, &imageProperties);
339 
340     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
341         TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32B32A32_UINT not supported");
342 
343     if (m_data.geometryShader)
344         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
345 
346     if (!(imageProperties.sampleCounts & m_data.samples))
347         TCU_THROW(NotSupportedError, "color buffer sample count not supported");
348 
349     if (m_data.numColorLayers > imageProperties.maxArrayLayers)
350         TCU_THROW(NotSupportedError, "color buffer layers not supported");
351 
352     if (m_data.useAttachment() && !context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
353         TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
354 
355     if (!context.getFragmentShadingRateProperties().fragmentShadingRateNonTrivialCombinerOps &&
356         ((m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR &&
357           m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
358          (m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR &&
359           m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
360         TCU_THROW(NotSupportedError, "fragmentShadingRateNonTrivialCombinerOps not supported");
361 
362     if (m_data.conservativeEnable)
363     {
364         context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
365         if (m_data.conservativeMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT &&
366             !context.getConservativeRasterizationPropertiesEXT().primitiveUnderestimation)
367             TCU_THROW(NotSupportedError, "primitiveUnderestimation not supported");
368     }
369 
370     if (m_data.fragStencil)
371         context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
372 
373     if (m_data.multiViewport &&
374         !context.getFragmentShadingRateProperties().primitiveFragmentShadingRateWithMultipleViewports)
375         TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateWithMultipleViewports not supported");
376 
377     if (m_data.srLayered && !context.getFragmentShadingRateProperties().layeredShadingRateAttachments)
378         TCU_THROW(NotSupportedError, "layeredShadingRateAttachments not supported");
379 
380     if ((m_data.multiViewport || m_data.colorLayered) && !m_data.geometryShader)
381         context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
382 
383     if (m_data.multiView && m_data.geometryShader && !context.getMultiviewFeatures().multiviewGeometryShader)
384         TCU_THROW(NotSupportedError, "multiviewGeometryShader not supported");
385 
386     if (m_data.interlock && !context.getFragmentShaderInterlockFeaturesEXT().fragmentShaderPixelInterlock)
387         TCU_THROW(NotSupportedError, "fragmentShaderPixelInterlock not supported");
388 
389     if (m_data.sampleLocations)
390     {
391         context.requireDeviceFunctionality("VK_EXT_sample_locations");
392         if (!(m_data.samples & context.getSampleLocationsPropertiesEXT().sampleLocationSampleCounts))
393             TCU_THROW(NotSupportedError, "samples not supported in sampleLocationSampleCounts");
394     }
395 
396     if (m_data.sampleMaskTest && !context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
397         TCU_THROW(NotSupportedError, "fragmentShadingRateWithSampleMask not supported");
398 
399 #ifndef CTS_USES_VULKANSC
400     if (m_data.meshShader)
401     {
402         context.requireDeviceFunctionality("VK_EXT_mesh_shader");
403         const auto &meshFeatures = context.getMeshShaderFeaturesEXT();
404 
405         if (m_data.shaderWritesRate && !meshFeatures.primitiveFragmentShadingRateMeshShader)
406             TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateMeshShader not supported");
407 
408         if (m_data.multiView && !meshFeatures.multiviewMeshShader)
409             TCU_THROW(NotSupportedError, "multiviewMeshShader not supported");
410     }
411 
412     checkPipelineConstructionRequirements(vki, physDev, m_data.groupParams->pipelineConstructionType);
413 
414     if (m_data.earlyAndLateTest)
415     {
416         context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
417         if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
418             TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
419     }
420 
421     if (m_data.maintenance6)
422         context.requireDeviceFunctionality("VK_KHR_maintenance6");
423 #endif
424 
425     if (m_data.sampleShadingEnable || m_data.sampleShadingInput)
426         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
427 }
428 
429 // Error codes writted by the fragment shader
430 enum
431 {
432     ERROR_NONE                     = 0,
433     ERROR_FRAGCOORD_CENTER         = 1,
434     ERROR_VTG_READBACK             = 2,
435     ERROR_FRAGCOORD_DERIV          = 3,
436     ERROR_FRAGCOORD_IMPLICIT_DERIV = 4,
437 };
438 
initPrograms(SourceCollections & programCollection) const439 void FSRTestCase::initPrograms(SourceCollections &programCollection) const
440 {
441     if (!m_data.meshShader)
442     {
443         std::stringstream vss;
444 
445         vss << "#version 450 core\n"
446                "#extension GL_EXT_fragment_shading_rate : enable\n"
447                "#extension GL_ARB_shader_viewport_layer_array : enable\n"
448                "layout(push_constant) uniform PC {\n"
449                "    int shadingRate;\n"
450                "} pc;\n"
451                "layout(location = 0) in vec2 pos;\n"
452                "layout(location = 0) out int instanceIndex;\n"
453                "layout(location = 1) out int readbackok;\n"
454                "layout(location = 2) out float zero;\n"
455                "out gl_PerVertex\n"
456                "{\n"
457                "   vec4 gl_Position;\n"
458                "};\n"
459                "void main()\n"
460                "{\n"
461                "  gl_Position = vec4(pos, 0, 1);\n"
462                "  instanceIndex = gl_InstanceIndex;\n"
463                "  readbackok = 1;\n"
464                "  zero = 0;\n";
465 
466         if (m_data.shaderWritesRate)
467         {
468             vss << "  gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
469 
470             // Verify that we can read from the output variable
471             vss << "  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
472 
473             if (!m_data.geometryShader)
474             {
475                 if (m_data.multiViewport)
476                     vss << "  gl_ViewportIndex = instanceIndex & 1;\n";
477                 if (m_data.colorLayered)
478                     vss << "  gl_Layer = ((instanceIndex & 2) >> 1);\n";
479             }
480         }
481 
482         vss << "}\n";
483 
484         programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
485         programCollection.glslSources.add("vert_1_2")
486             << glu::VertexSource(vss.str())
487             << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
488 
489         if (m_data.geometryShader)
490         {
491             std::string writeShadingRate = "";
492             if (m_data.shaderWritesRate)
493             {
494                 writeShadingRate = "  gl_PrimitiveShadingRateEXT = pc.shadingRate;\n"
495                                    "  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
496 
497                 if (m_data.multiViewport)
498                     writeShadingRate += "  gl_ViewportIndex = inInstanceIndex[0] & 1;\n";
499 
500                 if (m_data.colorLayered)
501                     writeShadingRate += "  gl_Layer = (inInstanceIndex[0] & 2) >> 1;\n";
502             }
503 
504             std::stringstream gss;
505             gss << "#version 450 core\n"
506                    "#extension GL_EXT_fragment_shading_rate : enable\n"
507                    "\n"
508                    "layout(push_constant) uniform PC {\n"
509                    "    int shadingRate;\n"
510                    "} pc;\n"
511                    "\n"
512                    "in gl_PerVertex\n"
513                    "{\n"
514                    "   vec4 gl_Position;\n"
515                    "} gl_in[3];\n"
516                    "\n"
517                    "layout(location = 0) in int inInstanceIndex[];\n"
518                    "layout(location = 0) out int outInstanceIndex;\n"
519                    "layout(location = 1) out int readbackok;\n"
520                    "layout(location = 2) out float zero;\n"
521                    "layout(triangles) in;\n"
522                    "layout(triangle_strip, max_vertices=3) out;\n"
523                    "\n"
524                    "out gl_PerVertex {\n"
525                    "   vec4 gl_Position;\n"
526                    "};\n"
527                    "\n"
528                    "void main(void)\n"
529                    "{\n"
530                    "   gl_Position = gl_in[0].gl_Position;\n"
531                    "   outInstanceIndex = inInstanceIndex[0];\n"
532                    "   readbackok  = 1;\n"
533                    "   zero = 0;\n"
534                 << writeShadingRate
535                 << "   EmitVertex();"
536                    "\n"
537                    "   gl_Position = gl_in[1].gl_Position;\n"
538                    "   outInstanceIndex = inInstanceIndex[1];\n"
539                    "   readbackok = 1;\n"
540                    "   zero = 0;\n"
541                 << writeShadingRate
542                 << "   EmitVertex();"
543                    "\n"
544                    "   gl_Position = gl_in[2].gl_Position;\n"
545                    "   outInstanceIndex = inInstanceIndex[2];\n"
546                    "   readbackok = 1;\n"
547                    "   zero = 0;\n"
548                 << writeShadingRate
549                 << "   EmitVertex();"
550                    "}\n";
551 
552             programCollection.glslSources.add("geom") << glu::GeometrySource(gss.str());
553         }
554     }
555     else
556     {
557         std::stringstream mss;
558 
559         mss << "#version 450 core\n"
560                "#extension GL_EXT_mesh_shader : enable\n";
561 
562         if (m_data.shaderWritesRate)
563         {
564             mss << "#extension GL_EXT_fragment_shading_rate : enable\n";
565         }
566 
567         mss << "layout(local_size_x=3) in;\n"
568                "layout(triangles) out;\n"
569                "layout(max_vertices=3, max_primitives=1) out;\n"
570                "layout(push_constant, std430) uniform PC {\n"
571                "  int shadingRate;\n"
572                "  uint instanceIndex;\n"
573                "} pc;\n"
574                "layout(set=1, binding=0, std430) readonly buffer PosBuffer {\n"
575                "  vec2 vertexPositions[];\n"
576                "} pb;\n"
577                "layout(location = 0) flat out int instanceIndex[];\n"
578                "layout(location = 1) flat out int readbackok[];\n"
579                "layout(location = 2) out float zero[];\n";
580 
581         if (m_data.shaderWritesRate)
582         {
583             mss << "perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
584                 << (m_data.colorLayered ? "  int gl_Layer;\n" : "")
585                 << (m_data.multiViewport ? "  int gl_ViewportIndex;\n" : "")
586                 << "  int gl_PrimitiveShadingRateEXT;\n"
587                    "} gl_MeshPrimitivesEXT[];\n";
588         }
589 
590         mss << "void main()\n"
591                "{\n"
592                "  SetMeshOutputsEXT(3u, 1u);\n"
593                "  const uint vertexIdx = (pc.instanceIndex * 3u + gl_LocalInvocationIndex);\n"
594                "  gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(pb.vertexPositions[vertexIdx], 0, "
595                "1);\n"
596                "  if (gl_LocalInvocationIndex == 0) {\n"
597                "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
598                "  }\n"
599                "  instanceIndex[gl_LocalInvocationIndex] = int(pc.instanceIndex);\n"
600                "  readbackok[gl_LocalInvocationIndex] = 1;\n"
601                "  zero[gl_LocalInvocationIndex] = 0;\n";
602 
603         if (m_data.shaderWritesRate)
604         {
605             mss << "  gl_MeshPrimitivesEXT[0].gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
606 
607             // gl_MeshPerPrimitiveEXT is write-only in mesh shaders, so we cannot verify the readback operation.
608             //mss << "  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
609 
610             if (m_data.multiViewport)
611                 mss << "  gl_MeshPrimitivesEXT[0].gl_ViewportIndex = int(pc.instanceIndex & 1);\n";
612             if (m_data.colorLayered)
613                 mss << "  gl_MeshPrimitivesEXT[0].gl_Layer = int((pc.instanceIndex & 2) >> 1);\n";
614         }
615 
616         mss << "}\n";
617 
618         const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
619         programCollection.glslSources.add("mesh") << glu::MeshSource(mss.str()) << buildOptions;
620     }
621 
622     std::stringstream fss;
623 
624     fss << "#version 450 core\n"
625            "#extension GL_EXT_fragment_shading_rate : enable\n"
626            "#extension GL_ARB_shader_stencil_export : enable\n"
627            "#extension GL_ARB_fragment_shader_interlock : enable\n";
628 
629     if (m_data.earlyAndLateTest)
630         fss << "#extension GL_AMD_shader_early_and_late_fragment_tests : enable\n";
631 
632     fss << "layout(location = 0) out uvec4 col0;\n"
633            "layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
634            "layout(set = 0, binding = 3) uniform usampler2D tex;\n"
635            "layout(location = 0) flat in int instanceIndex;\n"
636            "layout(location = 1) flat in int readbackok;\n"
637            "layout(location = 2) "
638         << (m_data.sampleShadingInput ? "sample " : "") << "in float zero;\n";
639 
640     if (m_data.earlyAndLateTest)
641         fss << "layout(early_and_late_fragment_tests_amd) in;\n";
642 
643     if (m_data.fragDepth && m_data.earlyAndLateTest)
644         fss << "layout(depth_less) out float gl_FragDepth;\n";
645 
646     if (m_data.fragStencil && m_data.earlyAndLateTest)
647         fss << "layout(stencil_ref_less_front_amd) out int gl_FragStencilRefARB;\n";
648 
649     if (m_data.interlock)
650         fss << "layout(pixel_interlock_ordered) in;\n";
651 
652     fss << "void main()\n"
653            "{\n";
654 
655     if (m_data.interlock)
656         fss << "  beginInvocationInterlockARB();\n";
657 
658     fss <<
659         // X component gets shading rate enum
660         "  col0.x = gl_ShadingRateEXT;\n"
661         "  col0.y = 0;\n"
662         // Z component gets packed primitiveID | atomic value
663         "  col0.z = (instanceIndex << 24) | ((atomicAdd(buf.counter, 1) + 1) & 0x00FFFFFFu);\n"
664         "  ivec2 fragCoordXY = ivec2(gl_FragCoord.xy);\n"
665         "  ivec2 fragSize = ivec2(1<<((gl_ShadingRateEXT/4)&3), 1<<(gl_ShadingRateEXT&3));\n"
666         // W component gets error code
667         "  col0.w = uint(zero)"
668         << (m_data.sampleShadingInput ? " * gl_SampleID" : "")
669         << ";\n"
670            "  if (((fragCoordXY - fragSize / 2) % fragSize) != ivec2(0,0))\n"
671            "    col0.w = "
672         << ERROR_FRAGCOORD_CENTER << ";\n";
673 
674     if (m_data.shaderWritesRate)
675     {
676         fss << "  if (readbackok != 1)\n"
677                "    col0.w = "
678             << ERROR_VTG_READBACK << ";\n";
679     }
680 
681     // When sample shading, gl_FragCoord is more likely to give bad derivatives,
682     // e.g. due to a partially covered quad having some pixels center sample and
683     // some sample at a sample location.
684     if (!m_data.sampleShadingEnable && !m_data.sampleShadingInput)
685     {
686         fss << "  if (dFdx(gl_FragCoord.xy) != ivec2(fragSize.x, 0) || dFdy(gl_FragCoord.xy) != ivec2(0, fragSize.y))\n"
687                "    col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (int(dFdx(gl_FragCoord.xy)) << 14) | "
688                "(int(dFdx(gl_FragCoord.xy)) << 8) | "
689             << ERROR_FRAGCOORD_DERIV << ";\n";
690 
691         fss << "  uint implicitDerivX = texture(tex, vec2(gl_FragCoord.x / textureSize(tex, 0).x, 0)).x;\n"
692                "  uint implicitDerivY = texture(tex, vec2(0, gl_FragCoord.y / textureSize(tex, 0).y)).x;\n"
693                "  if (implicitDerivX != fragSize.x || implicitDerivY != fragSize.y)\n"
694                "    col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (implicitDerivY << 14) | (implicitDerivX << 8) "
695                "| "
696             << ERROR_FRAGCOORD_IMPLICIT_DERIV << ";\n";
697     }
698     // Y component gets sample mask value
699     if (m_data.useSampleMaskIn)
700         fss << "  col0.y = gl_SampleMaskIn[0];\n";
701 
702     if (m_data.fragDepth)
703         fss << "  gl_FragDepth = float(instanceIndex) / float(" << NUM_TRIANGLES << ");\n";
704 
705     if (m_data.fragStencil)
706         fss << "  gl_FragStencilRefARB = instanceIndex;\n";
707 
708     if (m_data.interlock)
709         fss << "  endInvocationInterlockARB();\n";
710 
711     fss << "}\n";
712 
713     programCollection.glslSources.add("frag") << glu::FragmentSource(fss.str());
714 
715     std::stringstream css;
716 
717     std::string fsampType = m_data.samples > 1 ? "texture2DMSArray" : "texture2DArray";
718     std::string usampType = m_data.samples > 1 ? "utexture2DMSArray" : "utexture2DArray";
719 
720     // Compute shader copies color/depth/stencil to linear layout in buffer memory
721     css << "#version 450 core\n"
722            "#extension GL_EXT_samplerless_texture_functions : enable\n"
723            "layout(set = 0, binding = 1) uniform "
724         << usampType
725         << " colorTex;\n"
726            "layout(set = 0, binding = 2, std430) buffer Block0 { uvec4 b[]; } colorbuf;\n"
727            "layout(set = 0, binding = 4, std430) buffer Block1 { float b[]; } depthbuf;\n"
728            "layout(set = 0, binding = 5, std430) buffer Block2 { uint b[]; } stencilbuf;\n"
729            "layout(set = 0, binding = 6) uniform "
730         << fsampType
731         << " depthTex;\n"
732            "layout(set = 0, binding = 7) uniform "
733         << usampType
734         << " stencilTex;\n"
735            "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
736            "void main()\n"
737            "{\n"
738            "   for (int i = 0; i < "
739         << m_data.samples
740         << "; ++i) {\n"
741            "      uint idx = ((gl_GlobalInvocationID.z * "
742         << m_data.framebufferDim.height << " + gl_GlobalInvocationID.y) * " << m_data.framebufferDim.width
743         << " + gl_GlobalInvocationID.x) * " << m_data.samples
744         << " + i;\n"
745            "      colorbuf.b[idx] = texelFetch(colorTex, ivec3(gl_GlobalInvocationID.xyz), i);\n";
746 
747     if (m_data.fragDepth)
748         css << "      depthbuf.b[idx] = texelFetch(depthTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
749 
750     if (m_data.fragStencil)
751         css << "      stencilbuf.b[idx] = texelFetch(stencilTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
752 
753     css << "   }\n"
754            "}\n";
755 
756     programCollection.glslSources.add("comp") << glu::ComputeSource(css.str());
757 
758     // Vertex shader for simple rendering without FSR on another subpass
759     {
760         std::ostringstream src;
761         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
762             << "\n"
763             << "layout(location = 0) in vec4 in_position;\n"
764             << "\n"
765             << "out gl_PerVertex {\n"
766             << "    vec4 gl_Position;\n"
767             << "};\n"
768             << "\n"
769             << "void main(void)\n"
770             << "{\n"
771             << "    gl_Position = in_position;\n"
772             << "}\n";
773 
774         programCollection.glslSources.add("vert_simple") << glu::VertexSource(src.str());
775     }
776 
777     // Fragment shader for simple rendering without FSR on another subpass
778     {
779         std::ostringstream src;
780         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
781             << "\n"
782             << "#extension GL_EXT_fragment_shading_rate : enable\n"
783             << "#extension GL_ARB_shader_stencil_export : enable\n"
784             << "\n"
785             << "layout(location = 0) out uvec4 o_color;\n"
786             << "\n"
787             << "void main(void)\n"
788             << "{\n"
789             << "    if (gl_ShadingRateEXT == 0)\n"
790             << "        o_color = uvec4(128, 128, 128, 1);\n"
791             << "    else\n"
792             << "        o_color = uvec4(255, 0, 0, 1);\n"
793             << "\n";
794 
795         if (m_data.fragDepth)
796         {
797             src << "    if (gl_ShadingRateEXT == 0)\n"
798                 << "       gl_FragDepth = 0.4;\n"
799                 << "    else\n"
800                 << "       gl_FragDepth = 0.2;\n"
801                 << "\n";
802         }
803         if (m_data.fragStencil)
804         {
805             src << "    if (gl_ShadingRateEXT == 0)\n"
806                 << "       gl_FragStencilRefARB = 1;\n"
807                 << "    else\n"
808                 << "       gl_FragStencilRefARB = 2;\n";
809         }
810 
811         src << "}\n";
812 
813         programCollection.glslSources.add("frag_simple") << glu::FragmentSource(src.str());
814     }
815 }
816 
createInstance(Context & context) const817 TestInstance *FSRTestCase::createInstance(Context &context) const
818 {
819     return new FSRTestInstance(context, m_data);
820 }
821 
ShadingRateExtentToEnum(VkExtent2D ext) const822 int32_t FSRTestInstance::ShadingRateExtentToEnum(VkExtent2D ext) const
823 {
824     ext.width  = deCtz32(ext.width);
825     ext.height = deCtz32(ext.height);
826 
827     return (ext.width << 2) | ext.height;
828 }
829 
ShadingRateEnumToExtent(int32_t rate) const830 VkExtent2D FSRTestInstance::ShadingRateEnumToExtent(int32_t rate) const
831 {
832     VkExtent2D ret;
833     ret.width  = 1 << ((rate / 4) & 3);
834     ret.height = 1 << (rate & 3);
835 
836     return ret;
837 }
838 
Combine(VkExtent2D ext0,VkExtent2D ext1,VkFragmentShadingRateCombinerOpKHR comb) const839 VkExtent2D FSRTestInstance::Combine(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const
840 {
841     VkExtent2D ret;
842     switch (comb)
843     {
844     default:
845         DE_ASSERT(0);
846         // fallthrough
847     case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR:
848         return ext0;
849     case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR:
850         return ext1;
851     case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR:
852         ret = {de::min(ext0.width, ext1.width), de::min(ext0.height, ext1.height)};
853         return ret;
854     case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR:
855         ret = {de::max(ext0.width, ext1.width), de::max(ext0.height, ext1.height)};
856         return ret;
857     case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR:
858         ret = {ext0.width * ext1.width, ext0.height * ext1.height};
859         if (!m_shadingRateProperties.fragmentShadingRateStrictMultiplyCombiner)
860         {
861             if (ext0.width == 1 && ext1.width == 1)
862                 ret.width = 2;
863             if (ext0.height == 1 && ext1.height == 1)
864                 ret.height = 2;
865         }
866         return ret;
867     }
868 }
869 
CombineMasks(int32_t rateMask0,int32_t rateMask1,VkFragmentShadingRateCombinerOpKHR comb,bool allowUnclampedResult) const870 int32_t FSRTestInstance::CombineMasks(int32_t rateMask0, int32_t rateMask1, VkFragmentShadingRateCombinerOpKHR comb,
871                                       bool allowUnclampedResult) const
872 {
873     int32_t combinedMask = 0;
874 
875     for (int i = 0; i < 16; i++)
876     {
877         if (rateMask0 & (1 << i))
878         {
879             VkExtent2D rate0 = ShadingRateEnumToExtent(i);
880 
881             for (int j = 0; j < 16; j++)
882             {
883                 if (rateMask1 & (1 << j))
884                 {
885                     VkExtent2D combinerResult = Combine(rate0, ShadingRateEnumToExtent(j), comb);
886                     int32_t clampedResult     = ShadingRateExtentToClampedMask(combinerResult);
887 
888                     if (allowUnclampedResult)
889                     {
890                         combinedMask |= 1 << ShadingRateExtentToEnum(combinerResult);
891                     }
892 
893                     combinedMask |= clampedResult;
894                 }
895             }
896         }
897     }
898 
899     return combinedMask;
900 }
901 
Simulate(int32_t rate0,int32_t rate1,int32_t rate2)902 int32_t FSRTestInstance::Simulate(int32_t rate0, int32_t rate1, int32_t rate2)
903 {
904     bool allowUnclampedInputs = true;
905 
906 #ifndef CTS_USES_VULKANSC
907     if (m_data.maintenance6)
908     {
909         allowUnclampedInputs = !m_maintenance6Properties.fragmentShadingRateClampCombinerInputs;
910     }
911 #endif
912 
913     int32_t &cachedRate = m_simulateCache[(rate2 * m_simulateValueCount + rate1) * m_simulateValueCount + rate0];
914     if (cachedRate != ~0)
915         return cachedRate;
916 
917     const VkExtent2D extent0 = ShadingRateEnumToExtent(rate0);
918     const VkExtent2D extent1 = ShadingRateEnumToExtent(rate1);
919     const VkExtent2D extent2 = ShadingRateEnumToExtent(rate2);
920 
921     int32_t finalMask = 0;
922 
923     // Clamped and unclamped inputs.
924     const int32_t extentMask0 = ShadingRateExtentToClampedMask(extent0) | (1 << rate0);
925     const int32_t extentMask1 = ShadingRateExtentToClampedMask(extent1) | (1 << rate1);
926     const int32_t extentMask2 = ShadingRateExtentToClampedMask(extent2) | (1 << rate2);
927 
928     // Combine rate 0 and 1, get a mask of possible clamped rates
929     int32_t intermedMask =
930         CombineMasks(extentMask0, extentMask1, m_data.combinerOp[0], allowUnclampedInputs /* allowUnclampedResult */);
931 
932     // For each clamped rate, combine that with rate 2 and accumulate the possible clamped rates
933     for (int i = 0; i < 16; ++i)
934     {
935         if (intermedMask & (1 << i))
936         {
937             finalMask |=
938                 CombineMasks(intermedMask, extentMask2, m_data.combinerOp[1], false /* allowUnclampedResult */);
939         }
940     }
941 
942     if (Force1x1())
943         finalMask = 0x1;
944 
945     cachedRate = finalMask;
946     return finalMask;
947 }
948 
949 // If a rate is not valid (<=4x4), clamp it to something valid.
950 // This is only used for "inputs" to the system, not to mimic
951 // how the implementation internally clamps intermediate values.
SanitizeExtent(VkExtent2D ext) const952 VkExtent2D FSRTestInstance::SanitizeExtent(VkExtent2D ext) const
953 {
954     DE_ASSERT(ext.width > 0 && ext.height > 0);
955 
956     ext.width  = de::min(ext.width, 4u);
957     ext.height = de::min(ext.height, 4u);
958 
959     return ext;
960 }
961 
962 // Map an extent to a mask of all modes smaller than or equal to it in either dimension
ShadingRateExtentToClampedMask(VkExtent2D ext) const963 int32_t FSRTestInstance::ShadingRateExtentToClampedMask(VkExtent2D ext) const
964 {
965     const uint32_t shadingRateBit = (1 << ShadingRateExtentToEnum(ext));
966     uint32_t desiredSize          = ext.width * ext.height;
967     int32_t mask                  = 0;
968     int32_t swappedSizesMask      = 0;
969 
970     while (desiredSize > 0)
971     {
972         // First, find modes that maximize the area
973         for (uint32_t i = 0; i < m_supportedFragmentShadingRateCount; ++i)
974         {
975             const VkPhysicalDeviceFragmentShadingRateKHR &supportedRate = m_supportedFragmentShadingRates[i];
976             if ((supportedRate.sampleCounts & m_data.samples) &&
977                 supportedRate.fragmentSize.width * supportedRate.fragmentSize.height == desiredSize)
978             {
979                 if (supportedRate.fragmentSize.width <= ext.width && supportedRate.fragmentSize.height <= ext.height)
980                 {
981                     mask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
982                 }
983                 else if (supportedRate.fragmentSize.height <= ext.width &&
984                          supportedRate.fragmentSize.width <= ext.height)
985                 {
986                     swappedSizesMask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
987                 }
988             }
989         }
990         if (mask)
991         {
992             // Amongst the modes that maximize the area, pick the ones that
993             // minimize the aspect ratio. Prefer ratio of 1, then 2, then 4.
994             // 1x1 = 0, 2x2 = 5, 4x4 = 10
995             static const uint32_t aspectMaskRatio1 = 0x421;
996             // 2x1 = 4, 1x2 = 1, 4x2 = 9, 2x4 = 6
997             static const uint32_t aspectMaskRatio2 = 0x252;
998             // 4x1 = 8, 1x4 = 2,
999             static const uint32_t aspectMaskRatio4 = 0x104;
1000 
1001             if (mask & aspectMaskRatio1)
1002             {
1003                 mask &= aspectMaskRatio1;
1004                 break;
1005             }
1006             if (mask & aspectMaskRatio2)
1007             {
1008                 mask &= aspectMaskRatio2;
1009                 break;
1010             }
1011             if (mask & aspectMaskRatio4)
1012             {
1013                 mask &= aspectMaskRatio4;
1014                 break;
1015             }
1016             DE_ASSERT(0);
1017         }
1018         desiredSize /= 2;
1019     }
1020 
1021     // Optionally include the sizes with swapped width and height.
1022     mask |= swappedSizesMask;
1023 
1024     if (mask & shadingRateBit)
1025     {
1026         // The given shading rate is valid. Don't clamp it.
1027         return shadingRateBit;
1028     }
1029 
1030     // Return alternative shading rates.
1031     return mask;
1032 }
1033 
SanitizeRate(int32_t rate) const1034 int32_t FSRTestInstance::SanitizeRate(int32_t rate) const
1035 {
1036     VkExtent2D extent = ShadingRateEnumToExtent(rate);
1037 
1038     extent = SanitizeExtent(extent);
1039 
1040     return ShadingRateExtentToEnum(extent);
1041 }
1042 
1043 // Map primID % 9 to primitive shading rate
PrimIDToPrimitiveShadingRate(int32_t primID)1044 int32_t FSRTestInstance::PrimIDToPrimitiveShadingRate(int32_t primID)
1045 {
1046     int32_t &cachedRate = m_primIDToPrimitiveShadingRate[primID];
1047     if (cachedRate != ~0)
1048         return cachedRate;
1049 
1050     VkExtent2D extent;
1051     extent.width  = 1 << (primID % 3);
1052     extent.height = 1 << ((primID / 3) % 3);
1053 
1054     cachedRate = ShadingRateExtentToEnum(extent);
1055     return cachedRate;
1056 }
1057 
1058 // Map primID / 9 to pipeline shading rate
PrimIDToPipelineShadingRate(int32_t primID)1059 int32_t FSRTestInstance::PrimIDToPipelineShadingRate(int32_t primID)
1060 {
1061     int32_t &cachedRate = m_primIDToPipelineShadingRate[primID];
1062     if (cachedRate != ~0)
1063         return cachedRate;
1064 
1065     primID /= 9;
1066     VkExtent2D extent;
1067     extent.width  = 1 << (primID % 3);
1068     extent.height = 1 << ((primID / 3) % 3);
1069 
1070     cachedRate = ShadingRateExtentToEnum(extent);
1071     return cachedRate;
1072 }
1073 
CreateCachedBuffer(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkBufferCreateInfo & bufferCreateInfo)1074 static de::MovePtr<BufferWithMemory> CreateCachedBuffer(const vk::DeviceInterface &vk, const vk::VkDevice device,
1075                                                         vk::Allocator &allocator,
1076                                                         const vk::VkBufferCreateInfo &bufferCreateInfo)
1077 {
1078     try
1079     {
1080         return de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1081             vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Cached));
1082     }
1083     catch (const tcu::NotSupportedError &)
1084     {
1085         return de::MovePtr<BufferWithMemory>(
1086             new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1087     }
1088 }
1089 
iterate(void)1090 tcu::TestStatus FSRTestInstance::iterate(void)
1091 {
1092     const DeviceInterface &vk = m_context.getDeviceInterface();
1093     const VkDevice device     = m_context.getDevice();
1094     tcu::TestLog &log         = m_context.getTestContext().getLog();
1095     Allocator &allocator      = m_context.getDefaultAllocator();
1096     VkFlags allShaderStages   = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
1097     VkFlags allPipelineStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1098                                 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
1099                                 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
1100                                 VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1101     const VkFormat cbFormat = VK_FORMAT_R32G32B32A32_UINT;
1102     VkFormat dsFormat       = VK_FORMAT_UNDEFINED;
1103     const auto vertBufferUsage =
1104         (m_data.meshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1105 
1106     if (m_data.meshShader)
1107     {
1108 #ifndef CTS_USES_VULKANSC
1109         allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
1110         allPipelineStages |= VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT;
1111 #else
1112         DE_ASSERT(false);
1113 #endif // CTS_USES_VULKANSC
1114     }
1115     else
1116     {
1117         allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
1118         allPipelineStages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
1119 
1120         if (m_data.geometryShader)
1121         {
1122             allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
1123             allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
1124         }
1125     }
1126 
1127     if (m_data.useDepthStencil)
1128     {
1129         VkFormatProperties formatProps;
1130         m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(),
1131                                                                            VK_FORMAT_D32_SFLOAT_S8_UINT, &formatProps);
1132         if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
1133         {
1134             dsFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
1135         }
1136         else
1137         {
1138             dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1139         }
1140     }
1141 
1142     deRandom rnd;
1143     deRandom_init(&rnd, m_data.seed);
1144 
1145     qpTestResult res                 = QP_TEST_RESULT_PASS;
1146     uint32_t numUnexpected1x1Samples = 0;
1147     uint32_t numTotalSamples         = 0;
1148 
1149     enum AttachmentModes
1150     {
1151         ATTACHMENT_MODE_DEFAULT = 0,
1152         ATTACHMENT_MODE_LAYOUT_OPTIMAL,
1153         ATTACHMENT_MODE_IMAGELESS,
1154         ATTACHMENT_MODE_2DARRAY,
1155         ATTACHMENT_MODE_TILING_LINEAR,
1156 
1157         ATTACHMENT_MODE_COUNT,
1158     };
1159 
1160     uint32_t numSRLayers = m_data.srLayered ? 2u : 1u;
1161 
1162     VkExtent2D minFragmentShadingRateAttachmentTexelSize          = {1, 1};
1163     VkExtent2D maxFragmentShadingRateAttachmentTexelSize          = {1, 1};
1164     uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio = 1;
1165     if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
1166     {
1167         minFragmentShadingRateAttachmentTexelSize =
1168             m_context.getFragmentShadingRateProperties().minFragmentShadingRateAttachmentTexelSize;
1169         maxFragmentShadingRateAttachmentTexelSize =
1170             m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSize;
1171         maxFragmentShadingRateAttachmentTexelSizeAspectRatio =
1172             m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
1173     }
1174 
1175     VkDeviceSize atomicBufferSize = sizeof(uint32_t);
1176 
1177     de::MovePtr<BufferWithMemory> atomicBuffer;
1178     atomicBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1179         vk, device, allocator,
1180         makeBufferCreateInfo(atomicBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
1181         MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
1182 
1183     uint32_t *abuf = (uint32_t *)atomicBuffer->getAllocation().getHostPtr();
1184 
1185     // NUM_TRIANGLES triangles, 3 vertices, 2 components of float position
1186     VkDeviceSize vertexBufferSize = NUM_TRIANGLES * 3 * 2 * sizeof(float);
1187 
1188     de::MovePtr<BufferWithMemory> vertexBuffer;
1189     vertexBuffer = de::MovePtr<BufferWithMemory>(
1190         new BufferWithMemory(vk, device, allocator,
1191                              makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vertBufferUsage),
1192                              MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
1193 
1194     float *vbuf = (float *)vertexBuffer->getAllocation().getHostPtr();
1195     for (int32_t i = 0; i < (int32_t)(vertexBufferSize / sizeof(float)); ++i)
1196     {
1197         vbuf[i] = deRandom_getFloat(&rnd) * 2.0f - 1.0f;
1198     }
1199     flushAlloc(vk, device, vertexBuffer->getAllocation());
1200 
1201     VkDeviceSize colorOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples *
1202                                          4 * sizeof(uint32_t) * m_data.numColorLayers;
1203     de::MovePtr<BufferWithMemory> colorOutputBuffer =
1204         CreateCachedBuffer(vk, device, allocator,
1205                            makeBufferCreateInfo(colorOutputBufferSize,
1206                                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1207 
1208     de::MovePtr<BufferWithMemory> secColorOutputBuffer = CreateCachedBuffer(
1209         vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1210 
1211     VkDeviceSize depthOutputBufferSize = 0, stencilOutputBufferSize = 0;
1212     de::MovePtr<BufferWithMemory> depthOutputBuffer, stencilOutputBuffer;
1213     if (m_data.useDepthStencil)
1214     {
1215         depthOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples *
1216                                 sizeof(float) * m_data.numColorLayers;
1217         depthOutputBuffer =
1218             CreateCachedBuffer(vk, device, allocator,
1219                                makeBufferCreateInfo(depthOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1220                                                                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1221 
1222         stencilOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples *
1223                                   sizeof(uint32_t) * m_data.numColorLayers;
1224         stencilOutputBuffer =
1225             CreateCachedBuffer(vk, device, allocator,
1226                                makeBufferCreateInfo(stencilOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1227                                                                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1228     }
1229 
1230     uint32_t minSRTexelWidth  = minFragmentShadingRateAttachmentTexelSize.width;
1231     uint32_t minSRTexelHeight = minFragmentShadingRateAttachmentTexelSize.height;
1232     uint32_t maxSRWidth       = (m_data.framebufferDim.width + minSRTexelWidth - 1) / minSRTexelWidth;
1233     uint32_t maxSRHeight      = (m_data.framebufferDim.height + minSRTexelHeight - 1) / minSRTexelHeight;
1234 
1235     // max size over all formats
1236     VkDeviceSize srFillBufferSize = numSRLayers * maxSRWidth * maxSRHeight * 32 /*4 component 64-bit*/;
1237     de::MovePtr<BufferWithMemory> srFillBuffer;
1238     uint8_t *fillPtr = DE_NULL;
1239     if (m_data.useAttachment())
1240     {
1241         srFillBuffer = CreateCachedBuffer(vk, device, allocator,
1242                                           makeBufferCreateInfo(srFillBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
1243         fillPtr      = (uint8_t *)srFillBuffer->getAllocation().getHostPtr();
1244     }
1245 
1246     de::MovePtr<ImageWithMemory> cbImage;
1247     Move<VkImageView> cbImageView;
1248     {
1249         const VkImageCreateInfo imageCreateInfo = {
1250             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1251             DE_NULL,                             // const void* pNext;
1252             (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
1253             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1254             cbFormat,                            // VkFormat format;
1255             {
1256                 m_data.framebufferDim.width,  // uint32_t width;
1257                 m_data.framebufferDim.height, // uint32_t height;
1258                 1u                            // uint32_t depth;
1259             },                                // VkExtent3D extent;
1260             1u,                               // uint32_t mipLevels;
1261             m_data.numColorLayers,            // uint32_t arrayLayers;
1262             m_data.samples,                   // VkSampleCountFlagBits samples;
1263             VK_IMAGE_TILING_OPTIMAL,          // VkImageTiling tiling;
1264             cbUsage,                          // VkImageUsageFlags usage;
1265             VK_SHARING_MODE_EXCLUSIVE,        // VkSharingMode sharingMode;
1266             0u,                               // uint32_t queueFamilyIndexCount;
1267             DE_NULL,                          // const uint32_t* pQueueFamilyIndices;
1268             VK_IMAGE_LAYOUT_UNDEFINED         // VkImageLayout initialLayout;
1269         };
1270         cbImage = de::MovePtr<ImageWithMemory>(
1271             new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1272 
1273         VkImageViewCreateInfo imageViewCreateInfo = {
1274             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1275             DE_NULL,                                  // const void* pNext;
1276             (VkImageViewCreateFlags)0u,               // VkImageViewCreateFlags flags;
1277             **cbImage,                                // VkImage image;
1278             VK_IMAGE_VIEW_TYPE_2D_ARRAY,              // VkImageViewType viewType;
1279             cbFormat,                                 // VkFormat format;
1280             {
1281                 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1282                 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1283                 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1284                 VK_COMPONENT_SWIZZLE_A  // VkComponentSwizzle a;
1285             },                          // VkComponentMapping  components;
1286             {
1287                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1288                 0u,                        // uint32_t baseMipLevel;
1289                 1u,                        // uint32_t levelCount;
1290                 0u,                        // uint32_t baseArrayLayer;
1291                 m_data.numColorLayers      // uint32_t layerCount;
1292             }                              // VkImageSubresourceRange subresourceRange;
1293         };
1294         cbImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1295     }
1296 
1297     de::MovePtr<ImageWithMemory> secCbImage;
1298     Move<VkImageView> secCbImageView;
1299     if (m_data.multiSubpasses)
1300     {
1301         const VkImageCreateInfo imageCreateInfo = {
1302             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1303             DE_NULL,                             // const void* pNext;
1304             (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
1305             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1306             cbFormat,                            // VkFormat format;
1307             {
1308                 m_data.framebufferDim.width,  // uint32_t width;
1309                 m_data.framebufferDim.height, // uint32_t height;
1310                 1u                            // uint32_t depth;
1311             },                                // VkExtent3D extent;
1312             1u,                               // uint32_t mipLevels;
1313             1u,                               // uint32_t arrayLayers;
1314             VK_SAMPLE_COUNT_1_BIT,            // VkSampleCountFlagBits samples;
1315             VK_IMAGE_TILING_OPTIMAL,          // VkImageTiling tiling;
1316             cbUsage,                          // VkImageUsageFlags usage;
1317             VK_SHARING_MODE_EXCLUSIVE,        // VkSharingMode sharingMode;
1318             0u,                               // uint32_t queueFamilyIndexCount;
1319             DE_NULL,                          // const uint32_t* pQueueFamilyIndices;
1320             VK_IMAGE_LAYOUT_UNDEFINED         // VkImageLayout initialLayout;
1321         };
1322         secCbImage = de::MovePtr<ImageWithMemory>(
1323             new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1324 
1325         VkImageViewCreateInfo imageViewCreateInfo = {
1326             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1327             DE_NULL,                                  // const void* pNext;
1328             (VkImageViewCreateFlags)0u,               // VkImageViewCreateFlags flags;
1329             **secCbImage,                             // VkImage image;
1330             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
1331             cbFormat,                                 // VkFormat format;
1332             {
1333                 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1334                 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1335                 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1336                 VK_COMPONENT_SWIZZLE_A  // VkComponentSwizzle a;
1337             },                          // VkComponentMapping components;
1338             {
1339                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1340                 0u,                        // uint32_t baseMipLevel;
1341                 1u,                        // uint32_t levelCount;
1342                 0u,                        // uint32_t baseArrayLayer;
1343                 1u                         // uint32_t layerCount;
1344             }                              // VkImageSubresourceRange subresourceRange;
1345         };
1346         secCbImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1347     }
1348 
1349     de::MovePtr<ImageWithMemory> dsImage;
1350     Move<VkImageView> dsImageView, dImageView, sImageView;
1351 
1352     if (m_data.useDepthStencil)
1353     {
1354         const VkImageCreateInfo imageCreateInfo = {
1355             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1356             DE_NULL,                             // const void* pNext;
1357             (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
1358             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1359             dsFormat,                            // VkFormat format;
1360             {
1361                 m_data.framebufferDim.width * (1 << m_data.dsBaseMipLevel),  // uint32_t width;
1362                 m_data.framebufferDim.height * (1 << m_data.dsBaseMipLevel), // uint32_t height;
1363                 1u                                                           // uint32_t depth;
1364             },                                                               // VkExtent3D extent;
1365             m_data.dsBaseMipLevel + 1,                                       // uint32_t mipLevels;
1366             m_data.numColorLayers,                                           // uint32_t arrayLayers;
1367             m_data.samples,                                                  // VkSampleCountFlagBits samples;
1368             VK_IMAGE_TILING_OPTIMAL,                                         // VkImageTiling tiling;
1369             dsUsage,                                                         // VkImageUsageFlags usage;
1370             VK_SHARING_MODE_EXCLUSIVE,                                       // VkSharingMode sharingMode;
1371             0u,                                                              // uint32_t queueFamilyIndexCount;
1372             DE_NULL,                                                         // const uint32_t* pQueueFamilyIndices;
1373             VK_IMAGE_LAYOUT_UNDEFINED                                        // VkImageLayout initialLayout;
1374         };
1375         dsImage = de::MovePtr<ImageWithMemory>(
1376             new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1377 
1378         VkImageViewCreateInfo imageViewCreateInfo = {
1379             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1380             DE_NULL,                                  // const void* pNext;
1381             (VkImageViewCreateFlags)0u,               // VkImageViewCreateFlags flags;
1382             **dsImage,                                // VkImage image;
1383             VK_IMAGE_VIEW_TYPE_2D_ARRAY,              // VkImageViewType viewType;
1384             dsFormat,                                 // VkFormat format;
1385             {
1386                 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1387                 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1388                 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1389                 VK_COMPONENT_SWIZZLE_A  // VkComponentSwizzle a;
1390             },                          // VkComponentMapping  components;
1391             {
1392                 VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
1393                 m_data.dsBaseMipLevel,                                   // uint32_t baseMipLevel;
1394                 1u,                                                      // uint32_t levelCount;
1395                 0u,                                                      // uint32_t baseArrayLayer;
1396                 m_data.numColorLayers                                    // uint32_t layerCount;
1397             }                                                            // VkImageSubresourceRange subresourceRange;
1398         };
1399         dsImageView                                     = createImageView(vk, device, &imageViewCreateInfo, NULL);
1400         imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1401         dImageView                                      = createImageView(vk, device, &imageViewCreateInfo, NULL);
1402         imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1403         sImageView                                      = createImageView(vk, device, &imageViewCreateInfo, NULL);
1404     }
1405 
1406     // Image used to test implicit derivative calculations.
1407     // Filled with a value of 1<<lod.
1408     de::MovePtr<ImageWithMemory> derivImage;
1409     Move<VkImageView> derivImageView;
1410     VkImageUsageFlags derivUsage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1411 
1412     uint32_t derivNumLevels;
1413     {
1414         uint32_t maxDim = de::max(m_context.getFragmentShadingRateProperties().maxFragmentSize.width,
1415                                   m_context.getFragmentShadingRateProperties().maxFragmentSize.height);
1416         derivNumLevels  = 1 + deCtz32(maxDim);
1417         const VkImageCreateInfo imageCreateInfo = {
1418             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1419             DE_NULL,                             // const void* pNext;
1420             (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
1421             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1422             VK_FORMAT_R32_UINT,                  // VkFormat format;
1423             {
1424                 m_context.getFragmentShadingRateProperties().maxFragmentSize.width,  // uint32_t width;
1425                 m_context.getFragmentShadingRateProperties().maxFragmentSize.height, // uint32_t height;
1426                 1u                                                                   // uint32_t depth;
1427             },                                                                       // VkExtent3D extent;
1428             derivNumLevels,                                                          // uint32_t mipLevels;
1429             1u,                                                                      // uint32_t arrayLayers;
1430             VK_SAMPLE_COUNT_1_BIT,                                                   // VkSampleCountFlagBits samples;
1431             VK_IMAGE_TILING_OPTIMAL,                                                 // VkImageTiling tiling;
1432             derivUsage,                                                              // VkImageUsageFlags usage;
1433             VK_SHARING_MODE_EXCLUSIVE,                                               // VkSharingMode sharingMode;
1434             0u,                                                                      // uint32_t queueFamilyIndexCount;
1435             DE_NULL,                  // const uint32_t* pQueueFamilyIndices;
1436             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1437         };
1438         derivImage = de::MovePtr<ImageWithMemory>(
1439             new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1440 
1441         VkImageViewCreateInfo imageViewCreateInfo = {
1442             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1443             DE_NULL,                                  // const void* pNext;
1444             (VkImageViewCreateFlags)0u,               // VkImageViewCreateFlags flags;
1445             **derivImage,                             // VkImage image;
1446             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
1447             VK_FORMAT_R32_UINT,                       // VkFormat format;
1448             {
1449                 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1450                 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1451                 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1452                 VK_COMPONENT_SWIZZLE_A  // VkComponentSwizzle a;
1453             },                          // VkComponentMapping  components;
1454             {
1455                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1456                 0u,                        // uint32_t baseMipLevel;
1457                 derivNumLevels,            // uint32_t levelCount;
1458                 0u,                        // uint32_t baseArrayLayer;
1459                 1u                         // uint32_t layerCount;
1460             }                              // VkImageSubresourceRange subresourceRange;
1461         };
1462         derivImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1463     }
1464 
1465     // sampler used with derivImage
1466     const struct VkSamplerCreateInfo samplerInfo = {
1467         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
1468         DE_NULL,                               // pNext
1469         0u,                                    // flags
1470         VK_FILTER_NEAREST,                     // magFilter
1471         VK_FILTER_NEAREST,                     // minFilter
1472         VK_SAMPLER_MIPMAP_MODE_NEAREST,        // mipmapMode
1473         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
1474         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
1475         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
1476         0.0f,                                  // mipLodBias
1477         VK_FALSE,                              // anisotropyEnable
1478         1.0f,                                  // maxAnisotropy
1479         false,                                 // compareEnable
1480         VK_COMPARE_OP_ALWAYS,                  // compareOp
1481         0.0f,                                  // minLod
1482         (float)derivNumLevels,                 // maxLod
1483         VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // borderColor
1484         VK_FALSE,                              // unnormalizedCoords
1485     };
1486 
1487     Move<VkSampler> sampler = createSampler(vk, device, &samplerInfo);
1488 
1489     std::vector<Move<vk::VkDescriptorSetLayout>> descriptorSetLayouts;
1490     const VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
1491 
1492     const VkDescriptorSetLayoutBinding bindings[] = {
1493         {
1494             0u,                                // binding
1495             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1496             1u,                                // descriptorCount
1497             allShaderStages,                   // stageFlags
1498             DE_NULL,                           // pImmutableSamplers
1499         },
1500         {
1501             1u,                               // binding
1502             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1503             1u,                               // descriptorCount
1504             allShaderStages,                  // stageFlags
1505             DE_NULL,                          // pImmutableSamplers
1506         },
1507         {
1508             2u,                                // binding
1509             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1510             1u,                                // descriptorCount
1511             allShaderStages,                   // stageFlags
1512             DE_NULL,                           // pImmutableSamplers
1513         },
1514         {
1515             3u,                                        // binding
1516             VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // descriptorType
1517             1u,                                        // descriptorCount
1518             allShaderStages,                           // stageFlags
1519             DE_NULL,                                   // pImmutableSamplers
1520         },
1521         {
1522             4u,                                // binding
1523             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1524             1u,                                // descriptorCount
1525             allShaderStages,                   // stageFlags
1526             DE_NULL,                           // pImmutableSamplers
1527         },
1528         {
1529             5u,                                // binding
1530             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1531             1u,                                // descriptorCount
1532             allShaderStages,                   // stageFlags
1533             DE_NULL,                           // pImmutableSamplers
1534         },
1535         {
1536             6u,                               // binding
1537             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1538             1u,                               // descriptorCount
1539             allShaderStages,                  // stageFlags
1540             DE_NULL,                          // pImmutableSamplers
1541         },
1542         {
1543             7u,                               // binding
1544             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1545             1u,                               // descriptorCount
1546             allShaderStages,                  // stageFlags
1547             DE_NULL,                          // pImmutableSamplers
1548         },
1549     };
1550 
1551     // Create a layout and allocate a descriptor set for it.
1552     const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = {
1553         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1554         DE_NULL,                                                 // pNext
1555         layoutCreateFlags,                                       // flags
1556         static_cast<uint32_t>(de::arrayLength(bindings)),        // bindingCount
1557         &bindings[0]                                             // pBindings
1558     };
1559 
1560     descriptorSetLayouts.push_back(vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo));
1561 
1562     // Mesh shaders use set 1 binding 0 as the vertex buffer.
1563     if (m_data.meshShader)
1564     {
1565 #ifndef CTS_USES_VULKANSC
1566         const VkDescriptorSetLayoutBinding extraBinding = {
1567             0u,                                // binding
1568             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1569             1u,                                // descriptorCount
1570             VK_SHADER_STAGE_MESH_BIT_EXT,      // stageFlags
1571             DE_NULL,                           // pImmutableSamplers
1572         };
1573 
1574         const VkDescriptorSetLayoutCreateInfo extraSetLayoutCreateInfo = {
1575             vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1576             DE_NULL,                                                 // pNext
1577             layoutCreateFlags,                                       // flags
1578             1u,                                                      // bindingCount
1579             &extraBinding,                                           // pBindings
1580         };
1581 
1582         descriptorSetLayouts.push_back(vk::createDescriptorSetLayout(vk, device, &extraSetLayoutCreateInfo));
1583 #else
1584         DE_ASSERT(false);
1585 #endif // CTS_USES_VULKANSC
1586     }
1587 
1588     const uint32_t numConstants                 = (m_data.meshShader ? 2u : 1u);
1589     const uint32_t pushConstantSize             = (static_cast<uint32_t>(sizeof(int32_t)) * numConstants);
1590     const VkPushConstantRange pushConstantRange = {
1591         allShaderStages,  // VkShaderStageFlags stageFlags;
1592         0u,               // uint32_t offset;
1593         pushConstantSize, // uint32_t size;
1594     };
1595 
1596     std::vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw;
1597     descriptorSetLayoutsRaw.reserve(descriptorSetLayouts.size());
1598 
1599     std::transform(begin(descriptorSetLayouts), end(descriptorSetLayouts), std::back_inserter(descriptorSetLayoutsRaw),
1600                    [](const Move<VkDescriptorSetLayout> &elem) { return elem.get(); });
1601 
1602     const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
1603         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1604         DE_NULL,                                       // pNext
1605         (VkPipelineLayoutCreateFlags)0,
1606         static_cast<uint32_t>(descriptorSetLayoutsRaw.size()), // setLayoutCount
1607         de::dataOrNull(descriptorSetLayoutsRaw),               // pSetLayouts
1608         1u,                                                    // pushConstantRangeCount
1609         &pushConstantRange,                                    // pPushConstantRanges
1610     };
1611 
1612     PipelineLayoutWrapper pipelineLayout(m_data.groupParams->pipelineConstructionType, vk, device,
1613                                          &pipelineLayoutCreateInfo, NULL);
1614 
1615     const Unique<VkShaderModule> cs(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
1616 
1617     const VkPipelineShaderStageCreateInfo csShaderCreateInfo = {
1618         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1619         DE_NULL,
1620         (VkPipelineShaderStageCreateFlags)0,
1621         VK_SHADER_STAGE_COMPUTE_BIT, // stage
1622         *cs,                         // shader
1623         "main",
1624         DE_NULL, // pSpecializationInfo
1625     };
1626 
1627     const VkComputePipelineCreateInfo pipelineCreateInfo = {
1628         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1629         DE_NULL,
1630         0u,                 // flags
1631         csShaderCreateInfo, // cs
1632         *pipelineLayout,    // layout
1633         (vk::VkPipeline)0,  // basePipelineHandle
1634         0u,                 // basePipelineIndex
1635     };
1636     Move<VkPipeline> computePipeline = createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo, NULL);
1637 
1638     for (uint32_t modeIdx = 0; modeIdx < ATTACHMENT_MODE_COUNT; ++modeIdx)
1639     {
1640         // If we're not using an attachment, don't test all the different attachment modes
1641         if (modeIdx != ATTACHMENT_MODE_DEFAULT && !m_data.useAttachment())
1642             continue;
1643 
1644         // Consider all uint formats possible
1645         static const VkFormat srFillFormats[] = {
1646             VK_FORMAT_R8_UINT,  VK_FORMAT_R8G8_UINT,   VK_FORMAT_R8G8B8_UINT,    VK_FORMAT_R8G8B8A8_UINT,
1647             VK_FORMAT_R16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16B16_UINT, VK_FORMAT_R16G16B16A16_UINT,
1648             VK_FORMAT_R32_UINT, VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32A32_UINT,
1649             VK_FORMAT_R64_UINT, VK_FORMAT_R64G64_UINT, VK_FORMAT_R64G64B64_UINT, VK_FORMAT_R64G64B64A64_UINT,
1650         };
1651         // Only test all formats in the default mode
1652         uint32_t numFillFormats =
1653             modeIdx == ATTACHMENT_MODE_DEFAULT ? (uint32_t)(sizeof(srFillFormats) / sizeof(srFillFormats[0])) : 1u;
1654 
1655         // Iterate over all supported tile sizes and formats
1656         for (uint32_t srTexelWidth = minFragmentShadingRateAttachmentTexelSize.width;
1657              srTexelWidth <= maxFragmentShadingRateAttachmentTexelSize.width; srTexelWidth *= 2)
1658             for (uint32_t srTexelHeight = minFragmentShadingRateAttachmentTexelSize.height;
1659                  srTexelHeight <= maxFragmentShadingRateAttachmentTexelSize.height; srTexelHeight *= 2)
1660                 for (uint32_t formatIdx = 0; formatIdx < numFillFormats; ++formatIdx)
1661                 {
1662                     uint32_t aspectRatio = (srTexelHeight > srTexelWidth) ? (srTexelHeight / srTexelWidth) :
1663                                                                             (srTexelWidth / srTexelHeight);
1664                     if (aspectRatio > maxFragmentShadingRateAttachmentTexelSizeAspectRatio)
1665                         continue;
1666 
1667                     // Go through the loop only once when not using an attachment
1668                     if (!m_data.useAttachment() &&
1669                         (srTexelWidth != minFragmentShadingRateAttachmentTexelSize.width ||
1670                          srTexelHeight != minFragmentShadingRateAttachmentTexelSize.height || formatIdx != 0))
1671                         continue;
1672 
1673                     bool imagelessFB = modeIdx == ATTACHMENT_MODE_IMAGELESS;
1674 
1675                     uint32_t srWidth  = (m_data.framebufferDim.width + srTexelWidth - 1) / srTexelWidth;
1676                     uint32_t srHeight = (m_data.framebufferDim.height + srTexelHeight - 1) / srTexelHeight;
1677 
1678                     VkFormat srFormat  = srFillFormats[formatIdx];
1679                     uint32_t srFillBpp = tcu::getPixelSize(mapVkFormat(srFormat));
1680 
1681                     VkImageLayout srLayout = modeIdx == ATTACHMENT_MODE_LAYOUT_OPTIMAL ?
1682                                                  VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR :
1683                                                  VK_IMAGE_LAYOUT_GENERAL;
1684                     VkImageViewType srViewType =
1685                         modeIdx == ATTACHMENT_MODE_2DARRAY ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
1686                     VkImageTiling srTiling =
1687                         (modeIdx == ATTACHMENT_MODE_TILING_LINEAR) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1688 
1689                     VkFormatProperties srFormatProperties;
1690                     m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(),
1691                                                                                        srFormat, &srFormatProperties);
1692                     VkFormatFeatureFlags srFormatFeatures = srTiling == VK_IMAGE_TILING_LINEAR ?
1693                                                                 srFormatProperties.linearTilingFeatures :
1694                                                                 srFormatProperties.optimalTilingFeatures;
1695 
1696                     if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
1697                         !(srFormatFeatures & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
1698                     {
1699                         if (srFormat == VK_FORMAT_R8_UINT && srTiling == VK_IMAGE_TILING_OPTIMAL)
1700                         {
1701                             log << tcu::TestLog::Message
1702                                 << "VK_FORMAT_R8_UINT/VK_IMAGE_TILING_OPTIMAL don't support "
1703                                    "VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"
1704                                 << tcu::TestLog::EndMessage;
1705                             res = QP_TEST_RESULT_FAIL;
1706                         }
1707                         continue;
1708                     }
1709 
1710                     Move<vk::VkDescriptorPool> descriptorPool;
1711                     std::vector<Move<vk::VkDescriptorSet>> descriptorSets;
1712                     VkDescriptorPoolCreateFlags poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1713 
1714                     vk::DescriptorPoolBuilder poolBuilder;
1715                     for (int32_t i = 0; i < (int32_t)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1716                         poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1717                     if (m_data.meshShader)
1718                         poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1719 
1720                     descriptorPool = poolBuilder.build(vk, device, poolCreateFlags,
1721                                                        static_cast<uint32_t>(descriptorSetLayouts.size()));
1722                     for (const auto &setLayout : descriptorSetLayouts)
1723                         descriptorSets.push_back(makeDescriptorSet(vk, device, *descriptorPool, *setLayout));
1724 
1725                     const auto mainDescriptorSet = descriptorSets.front().get();
1726 
1727                     de::MovePtr<ImageWithMemory> srImage;
1728                     Move<VkImageView> srImageView;
1729                     VkImageUsageFlags srUsage = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1730                                                 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1731 
1732                     if (m_data.useAttachment())
1733                     {
1734                         const VkImageCreateInfo imageCreateInfo = {
1735                             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1736                             DE_NULL,                             // const void* pNext;
1737                             (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
1738                             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1739                             srFormat,                            // VkFormat format;
1740                             {
1741                                 srWidth,               // uint32_t width;
1742                                 srHeight,              // uint32_t height;
1743                                 1u                     // uint32_t depth;
1744                             },                         // VkExtent3D extent;
1745                             1u,                        // uint32_t mipLevels;
1746                             numSRLayers,               // uint32_t arrayLayers;
1747                             VK_SAMPLE_COUNT_1_BIT,     // VkSampleCountFlagBits samples;
1748                             srTiling,                  // VkImageTiling tiling;
1749                             srUsage,                   // VkImageUsageFlags usage;
1750                             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1751                             0u,                        // uint32_t queueFamilyIndexCount;
1752                             DE_NULL,                   // const uint32_t* pQueueFamilyIndices;
1753                             VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout initialLayout;
1754                         };
1755                         srImage = de::MovePtr<ImageWithMemory>(
1756                             new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1757 
1758                         VkImageViewCreateInfo imageViewCreateInfo = {
1759                             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1760                             DE_NULL,                                  // const void* pNext;
1761                             (VkImageViewCreateFlags)0u,               // VkImageViewCreateFlags flags;
1762                             **srImage,                                // VkImage image;
1763                             srViewType,                               // VkImageViewType viewType;
1764                             srFormat,                                 // VkFormat format;
1765                             {
1766                                 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1767                                 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1768                                 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1769                                 VK_COMPONENT_SWIZZLE_A  // VkComponentSwizzle a;
1770                             },                          // VkComponentMapping  components;
1771                             {
1772                                 VK_IMAGE_ASPECT_COLOR_BIT,                             // VkImageAspectFlags aspectMask;
1773                                 0u,                                                    // uint32_t baseMipLevel;
1774                                 1u,                                                    // uint32_t levelCount;
1775                                 0u,                                                    // uint32_t baseArrayLayer;
1776                                 srViewType == VK_IMAGE_VIEW_TYPE_2D ? 1 : numSRLayers, // uint32_t layerCount;
1777                             } // VkImageSubresourceRange subresourceRange;
1778                         };
1779                         srImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1780                     }
1781 
1782                     VkDescriptorImageInfo imageInfo;
1783                     VkDescriptorBufferInfo bufferInfo;
1784 
1785                     VkWriteDescriptorSet w = {
1786                         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1787                         DE_NULL,                                // pNext
1788                         descriptorSets.front().get(),           // dstSet
1789                         (uint32_t)0,                            // dstBinding
1790                         0,                                      // dstArrayElement
1791                         1u,                                     // descriptorCount
1792                         bindings[0].descriptorType,             // descriptorType
1793                         &imageInfo,                             // pImageInfo
1794                         &bufferInfo,                            // pBufferInfo
1795                         DE_NULL,                                // pTexelBufferView
1796                     };
1797 
1798                     abuf[0] = 0;
1799                     flushAlloc(vk, device, atomicBuffer->getAllocation());
1800 
1801                     bufferInfo       = makeDescriptorBufferInfo(**atomicBuffer, 0, atomicBufferSize);
1802                     w.dstBinding     = 0;
1803                     w.descriptorType = bindings[0].descriptorType;
1804                     vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1805 
1806                     imageInfo        = makeDescriptorImageInfo(DE_NULL, *cbImageView, VK_IMAGE_LAYOUT_GENERAL);
1807                     w.dstBinding     = 1;
1808                     w.descriptorType = bindings[1].descriptorType;
1809                     vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1810 
1811                     bufferInfo       = makeDescriptorBufferInfo(**colorOutputBuffer, 0, colorOutputBufferSize);
1812                     w.dstBinding     = 2;
1813                     w.descriptorType = bindings[2].descriptorType;
1814                     vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1815 
1816                     imageInfo        = makeDescriptorImageInfo(*sampler, *derivImageView, VK_IMAGE_LAYOUT_GENERAL);
1817                     w.dstBinding     = 3;
1818                     w.descriptorType = bindings[3].descriptorType;
1819                     vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1820 
1821                     if (m_data.useDepthStencil)
1822                     {
1823                         bufferInfo       = makeDescriptorBufferInfo(**depthOutputBuffer, 0, depthOutputBufferSize);
1824                         w.dstBinding     = 4;
1825                         w.descriptorType = bindings[4].descriptorType;
1826                         vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1827 
1828                         bufferInfo       = makeDescriptorBufferInfo(**stencilOutputBuffer, 0, stencilOutputBufferSize);
1829                         w.dstBinding     = 5;
1830                         w.descriptorType = bindings[5].descriptorType;
1831                         vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1832 
1833                         imageInfo        = makeDescriptorImageInfo(DE_NULL, *dImageView, VK_IMAGE_LAYOUT_GENERAL);
1834                         w.dstBinding     = 6;
1835                         w.descriptorType = bindings[6].descriptorType;
1836                         vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1837 
1838                         imageInfo        = makeDescriptorImageInfo(DE_NULL, *sImageView, VK_IMAGE_LAYOUT_GENERAL);
1839                         w.dstBinding     = 7;
1840                         w.descriptorType = bindings[7].descriptorType;
1841                         vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1842                     }
1843 
1844                     // Update vertex buffer descriptor.
1845                     if (m_data.meshShader)
1846                     {
1847                         const auto extraBufferInfo =
1848                             makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
1849                         const VkWriteDescriptorSet extraWrite = {
1850                             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1851                             DE_NULL,                                // pNext
1852                             descriptorSets.back().get(),            // dstSet
1853                             (uint32_t)0,                            // dstBinding
1854                             0,                                      // dstArrayElement
1855                             1u,                                     // descriptorCount
1856                             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,      // descriptorType
1857                             nullptr,                                // pImageInfo
1858                             &extraBufferInfo,                       // pBufferInfo
1859                             DE_NULL,                                // pTexelBufferView
1860                         };
1861 
1862                         vk.updateDescriptorSets(device, 1u, &extraWrite, 0u, nullptr);
1863                     }
1864 
1865                     RenderPassWrapper renderPass;
1866 
1867                     std::vector<VkImage> images;
1868                     std::vector<VkImageView> attachments;
1869                     images.push_back(**cbImage);
1870                     attachments.push_back(*cbImageView);
1871                     uint32_t dsAttachmentIdx = 0, srAttachmentIdx = 0, secAttachmentIdx = 0;
1872                     if (m_data.useAttachment())
1873                     {
1874                         srAttachmentIdx = (uint32_t)attachments.size();
1875                         images.push_back(**srImage);
1876                         attachments.push_back(*srImageView);
1877                     }
1878                     if (m_data.useDepthStencil)
1879                     {
1880                         dsAttachmentIdx = (uint32_t)attachments.size();
1881                         images.push_back(**dsImage);
1882                         attachments.push_back(*dsImageView);
1883                     }
1884                     if (m_data.multiSubpasses)
1885                     {
1886                         secAttachmentIdx = (uint32_t)attachments.size();
1887                         images.push_back(**secCbImage);
1888                         attachments.push_back(*secCbImageView);
1889                     }
1890 
1891                     if (!m_data.groupParams->useDynamicRendering)
1892                     {
1893                         const vk::VkAttachmentReference2 colorAttachmentReference{
1894                             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1895                             DE_NULL,                                  // pNext
1896                             0,                                        // attachment
1897                             vk::VK_IMAGE_LAYOUT_GENERAL,              // layout
1898                             0,                                        // aspectMask
1899                         };
1900 
1901                         const vk::VkAttachmentReference2 colorAttachmentReference2{
1902                             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1903                             DE_NULL,                                  // pNext
1904                             secAttachmentIdx,                         // attachment
1905                             vk::VK_IMAGE_LAYOUT_GENERAL,              // layout
1906                             0,                                        // aspectMask
1907                         };
1908 
1909                         const vk::VkAttachmentReference2 fragmentShadingRateAttachment = {
1910                             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1911                             DE_NULL,                                  // pNext
1912                             srAttachmentIdx,                          // attachment
1913                             srLayout,                                 // layout
1914                             0,                                        // aspectMask
1915                         };
1916 
1917                         const vk::VkAttachmentReference2 depthAttachmentReference = {
1918                             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1919                             DE_NULL,                                  // pNext
1920                             dsAttachmentIdx,                          // attachment
1921                             vk::VK_IMAGE_LAYOUT_GENERAL,              // layout
1922                             0,                                        // aspectMask
1923                         };
1924 
1925                         const bool noAttachmentPtr = (m_data.attachmentUsage == AttachmentUsage::NO_ATTACHMENT_PTR);
1926                         const VkFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo = {
1927                             VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType   sType;
1928                             DE_NULL,                                                     // const void*   pNext;
1929                             (noAttachmentPtr ?
1930                                  nullptr :
1931                                  &fragmentShadingRateAttachment), // const VkAttachmentReference2* pFragmentShadingRateAttachment;
1932                             {srTexelWidth, srTexelHeight}, // VkExtent2D    shadingRateAttachmentTexelSize;
1933                         };
1934 
1935                         const bool useAttachmentInfo = (m_data.attachmentUsage != AttachmentUsage::NO_ATTACHMENT);
1936                         const VkSubpassDescription2 subpassDesc = {
1937                             VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,                      // sType
1938                             (useAttachmentInfo ? &shadingRateAttachmentInfo : nullptr),   // pNext;
1939                             (vk::VkSubpassDescriptionFlags)0,                             // flags
1940                             vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                          // pipelineBindPoint
1941                             m_data.multiView ? 0x3 : 0u,                                  // viewMask
1942                             0u,                                                           // inputCount
1943                             DE_NULL,                                                      // pInputAttachments
1944                             1,                                                            // colorCount
1945                             &colorAttachmentReference,                                    // pColorAttachments
1946                             DE_NULL,                                                      // pResolveAttachments
1947                             m_data.useDepthStencil ? &depthAttachmentReference : DE_NULL, // depthStencilAttachment
1948                             0u,                                                           // preserveCount
1949                             DE_NULL,                                                      // pPreserveAttachments
1950                         };
1951 
1952                         const VkSubpassDescription2 secSubpassDesc = {
1953                             VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,                      // sType
1954                             nullptr,                                                      // pNext;
1955                             (vk::VkSubpassDescriptionFlags)0,                             // flags
1956                             vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                          // pipelineBindPoint
1957                             0u,                                                           // viewMask
1958                             0u,                                                           // inputCount
1959                             nullptr,                                                      // pInputAttachments
1960                             1,                                                            // colorCount
1961                             &colorAttachmentReference2,                                   // pColorAttachments
1962                             nullptr,                                                      // pResolveAttachments
1963                             m_data.useDepthStencil ? &depthAttachmentReference : nullptr, // depthStencilAttachment
1964                             0u,                                                           // preserveCount
1965                             nullptr,                                                      // pPreserveAttachments
1966                         };
1967 
1968                         std::vector<VkSubpassDescription2> subpassDescriptions = {subpassDesc};
1969 
1970                         if (m_data.multiSubpasses)
1971                             subpassDescriptions.push_back(secSubpassDesc);
1972 
1973                         std::vector<VkAttachmentDescription2> attachmentDescriptions{{
1974                             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1975                             DE_NULL,                                    // const void* pNext;
1976                             (VkAttachmentDescriptionFlags)0u,           // VkAttachmentDescriptionFlags flags;
1977                             cbFormat,                                   // VkFormat format;
1978                             m_data.samples,                             // VkSampleCountFlagBits samples;
1979                             VK_ATTACHMENT_LOAD_OP_LOAD,                 // VkAttachmentLoadOp loadOp;
1980                             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
1981                             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
1982                             VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
1983                             VK_IMAGE_LAYOUT_GENERAL,                    // VkImageLayout initialLayout;
1984                             VK_IMAGE_LAYOUT_GENERAL                     // VkImageLayout finalLayout;
1985                         }};
1986 
1987                         std::vector<VkSubpassDependency2> subpassDependencies;
1988 
1989                         if (m_data.useAttachment())
1990                             attachmentDescriptions.push_back({
1991                                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1992                                 DE_NULL,                                    // const void* pNext;
1993                                 (VkAttachmentDescriptionFlags)0u,           // VkAttachmentDescriptionFlags flags;
1994                                 srFormat,                                   // VkFormat format;
1995                                 VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
1996                                 VK_ATTACHMENT_LOAD_OP_LOAD,                 // VkAttachmentLoadOp loadOp;
1997                                 VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
1998                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
1999                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
2000                                 srLayout,                                   // VkImageLayout initialLayout;
2001                                 srLayout                                    // VkImageLayout finalLayout;
2002                             });
2003 
2004                         if (m_data.useDepthStencil)
2005                         {
2006                             attachmentDescriptions.push_back({
2007                                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
2008                                 DE_NULL,                                    // const void* pNext;
2009                                 (VkAttachmentDescriptionFlags)0u,           // VkAttachmentDescriptionFlags flags;
2010                                 dsFormat,                                   // VkFormat format;
2011                                 m_data.samples,                             // VkSampleCountFlagBits samples;
2012                                 (m_data.dsClearOp                           // VkAttachmentLoadOp loadOp;
2013                                      ?
2014                                      VK_ATTACHMENT_LOAD_OP_CLEAR :
2015                                      VK_ATTACHMENT_LOAD_OP_LOAD),
2016                                 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
2017                                 VK_ATTACHMENT_LOAD_OP_LOAD,   // VkAttachmentLoadOp stencilLoadOp;
2018                                 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
2019                                 VK_IMAGE_LAYOUT_GENERAL,      // VkImageLayout initialLayout;
2020                                 VK_IMAGE_LAYOUT_GENERAL       // VkImageLayout finalLayout;
2021                             });
2022                         }
2023 
2024                         if (m_data.multiSubpasses)
2025                         {
2026                             attachmentDescriptions.push_back({
2027                                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
2028                                 DE_NULL,                                    // const void* pNext;
2029                                 (VkAttachmentDescriptionFlags)0u,           // VkAttachmentDescriptionFlags flags;
2030                                 cbFormat,                                   // VkFormat format;
2031                                 VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
2032                                 VK_ATTACHMENT_LOAD_OP_LOAD,                 // VkAttachmentLoadOp loadOp;
2033                                 VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
2034                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
2035                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
2036                                 VK_IMAGE_LAYOUT_GENERAL,                    // VkImageLayout initialLayout;
2037                                 VK_IMAGE_LAYOUT_GENERAL                     // VkImageLayout finalLayout;
2038                             });
2039 
2040                             subpassDependencies.push_back({
2041                                 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, // VkStructureType         sType;
2042                                 nullptr,                                // const void*             pNext;
2043                                 VK_SUBPASS_EXTERNAL,                    // uint32_t                srcSubpass;
2044                                 0,                                      // uint32_t                srcSubpass;
2045                                 0,                                      // VkPipelineStageFlags    srcStageMask;
2046                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2047                                     VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
2048                                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags    dstStageMask;
2049                                 0,                                             // VkAccessFlags           srcAccessMask;
2050                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2051                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags           dstAccessMask;
2052                                 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags       dependencyFlags;
2053                                 0                            // int32_t                 viewOffset;
2054                             });
2055 
2056                             subpassDependencies.push_back({
2057                                 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, // VkStructureType         sType;
2058                                 nullptr,                                // const void*             pNext;
2059                                 0,                                      // uint32_t                srcSubpass;
2060                                 1,                                      // uint32_t                dstSubpass;
2061                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2062                                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags    srcStageMask;
2063                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2064                                     VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags    dstStageMask;
2065                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2066                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags           srcAccessMask;
2067                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2068                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags           dstAccessMask;
2069                                 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags       dependencyFlags;
2070                                 0                            // int32_t                 viewOffset;
2071                             });
2072                         }
2073 
2074                         const uint32_t correlatedViewMask              = 0x3;
2075                         const VkRenderPassCreateInfo2 renderPassParams = {
2076                             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // sType
2077                             DE_NULL,                                     // pNext
2078                             (vk::VkRenderPassCreateFlags)0,
2079                             (uint32_t)attachmentDescriptions.size(),                   // attachmentCount
2080                             &attachmentDescriptions[0],                                // pAttachments
2081                             (uint32_t)subpassDescriptions.size(),                      // subpassCount
2082                             &subpassDescriptions[0],                                   // pSubpasses
2083                             (uint32_t)subpassDependencies.size(),                      // dependencyCount
2084                             m_data.multiSubpasses ? &subpassDependencies[0] : nullptr, // pDependencies
2085                             m_data.correlationMask,                                    // correlatedViewMaskCount
2086                             m_data.correlationMask ? &correlatedViewMask : DE_NULL     // pCorrelatedViewMasks
2087                         };
2088 
2089                         renderPass = RenderPassWrapper(m_data.groupParams->pipelineConstructionType, vk, device,
2090                                                        &renderPassParams);
2091 
2092                         std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo;
2093                         framebufferAttachmentImageInfo.push_back({
2094                             VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, //  VkStructureType sType;
2095                             DE_NULL,                                             //  const void* pNext;
2096                             (VkImageCreateFlags)0u,                              //  VkImageCreateFlags flags;
2097                             cbUsage,                                             //  VkImageUsageFlags usage;
2098                             m_data.framebufferDim.width,                         //  uint32_t width;
2099                             m_data.framebufferDim.height,                        //  uint32_t height;
2100                             m_data.numColorLayers,                               //  uint32_t layerCount;
2101                             1u,                                                  //  uint32_t viewFormatCount;
2102                             &cbFormat                                            //  const VkFormat* pViewFormats;
2103                         });
2104                         if (m_data.useAttachment())
2105                             framebufferAttachmentImageInfo.push_back({
2106                                 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,   //  VkStructureType sType;
2107                                 DE_NULL,                                               //  const void* pNext;
2108                                 (VkImageCreateFlags)0u,                                //  VkImageCreateFlags flags;
2109                                 srUsage,                                               //  VkImageUsageFlags usage;
2110                                 srWidth,                                               //  uint32_t width;
2111                                 srHeight,                                              //  uint32_t height;
2112                                 srViewType == VK_IMAGE_VIEW_TYPE_2D ? 1 : numSRLayers, //  uint32_t layerCount;
2113                                 1u,                                                    //  uint32_t viewFormatCount;
2114                                 &srFormat                                              //  const VkFormat* pViewFormats;
2115                             });
2116 
2117                         if (m_data.useDepthStencil)
2118                             framebufferAttachmentImageInfo.push_back({
2119                                 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, //  VkStructureType sType;
2120                                 DE_NULL,                                             //  const void* pNext;
2121                                 (VkImageCreateFlags)0u,                              //  VkImageCreateFlags flags;
2122                                 dsUsage,                                             //  VkImageUsageFlags usage;
2123                                 m_data.framebufferDim.width,                         //  uint32_t width;
2124                                 m_data.framebufferDim.height,                        //  uint32_t height;
2125                                 m_data.numColorLayers,                               //  uint32_t layerCount;
2126                                 1u,                                                  //  uint32_t viewFormatCount;
2127                                 &dsFormat                                            //  const VkFormat* pViewFormats;
2128                             });
2129 
2130                         if (m_data.multiSubpasses)
2131                             framebufferAttachmentImageInfo.push_back({
2132                                 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, //  VkStructureType sType;
2133                                 DE_NULL,                                             //  const void* pNext;
2134                                 (VkImageCreateFlags)0u,                              //  VkImageCreateFlags flags;
2135                                 cbUsage,                                             //  VkImageUsageFlags usage;
2136                                 m_data.framebufferDim.width,                         //  uint32_t width;
2137                                 m_data.framebufferDim.height,                        //  uint32_t height;
2138                                 1u,                                                  //  uint32_t layerCount;
2139                                 1u,                                                  //  uint32_t viewFormatCount;
2140                                 &cbFormat                                            //  const VkFormat* pViewFormats;
2141                             });
2142 
2143                         const VkFramebufferAttachmentsCreateInfo framebufferAttachmentsCreateInfo = {
2144                             VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, //  VkStructureType sType;
2145                             DE_NULL,                                               //  const void* pNext;
2146                             (uint32_t)framebufferAttachmentImageInfo.size(), //  uint32_t attachmentImageInfoCount;
2147                             &framebufferAttachmentImageInfo
2148                                 [0] //  const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos;
2149                         };
2150 
2151                         const vk::VkFramebufferCreateInfo framebufferParams = {
2152                             vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,             // sType
2153                             imagelessFB ? &framebufferAttachmentsCreateInfo : DE_NULL, // pNext
2154                             (vk::VkFramebufferCreateFlags)(imagelessFB ? VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT : 0),
2155                             *renderPass,                                  // renderPass
2156                             (uint32_t)attachments.size(),                 // attachmentCount
2157                             imagelessFB ? DE_NULL : &attachments[0],      // pAttachments
2158                             m_data.framebufferDim.width,                  // width
2159                             m_data.framebufferDim.height,                 // height
2160                             m_data.multiView ? 1 : m_data.numColorLayers, // layers
2161                         };
2162 
2163                         renderPass.createFramebuffer(vk, device, &framebufferParams, images);
2164                     }
2165 
2166                     const VkVertexInputBindingDescription vertexBinding = {
2167                         0u,                         // uint32_t binding;
2168                         sizeof(float) * 2,          // uint32_t stride;
2169                         VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
2170                     };
2171                     const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
2172                         0u,                      // uint32_t location;
2173                         0u,                      // uint32_t binding;
2174                         VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
2175                         0u                       // uint32_t offset;
2176                     };
2177 
2178                     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
2179                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2180                         DE_NULL,                                                   // const void* pNext;
2181                         (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
2182                         1u,                                       // uint32_t vertexBindingDescriptionCount;
2183                         &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2184                         1u,             // uint32_t vertexAttributeDescriptionCount;
2185                         &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2186                     };
2187 
2188                     const VkPipelineRasterizationConservativeStateCreateInfoEXT consRastState = {
2189                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT, // VkStructureType    sType;
2190                         DE_NULL,                                                   // const void*    pNext;
2191                         (VkPipelineRasterizationConservativeStateCreateFlagsEXT)0, // VkPipelineRasterizationConservativeStateCreateFlagsEXT flags;
2192                         m_data.conservativeMode, // VkConservativeRasterizationModeEXT conservativeRasterizationMode;
2193                         0.0f,                    // float  extraPrimitiveOverestimationSize;
2194                     };
2195 
2196                     const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
2197                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2198                         m_data.conservativeEnable ? &consRastState : DE_NULL,       // const void* pNext;
2199                         (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
2200                         VK_FALSE,                                   // VkBool32 depthClampEnable;
2201                         VK_FALSE,                                   // VkBool32 rasterizerDiscardEnable;
2202                         VK_POLYGON_MODE_FILL,                       // VkPolygonMode polygonMode;
2203                         VK_CULL_MODE_NONE,                          // VkCullModeFlags cullMode;
2204                         VK_FRONT_FACE_CLOCKWISE,                    // VkFrontFace frontFace;
2205                         VK_FALSE,                                   // VkBool32 depthBiasEnable;
2206                         0.0f,                                       // float depthBiasConstantFactor;
2207                         0.0f,                                       // float depthBiasClamp;
2208                         0.0f,                                       // float depthBiasSlopeFactor;
2209                         1.0f                                        // float lineWidth;
2210                     };
2211 
2212                     // Kill some bits from each AA mode
2213                     const VkSampleMask sampleMask   = m_data.sampleMaskTest ? 0x9 : 0x7D56;
2214                     const VkSampleMask *pSampleMask = m_data.useApiSampleMask ? &sampleMask : DE_NULL;
2215 
2216                     // All samples at pixel center. We'll validate that pixels are fully covered or uncovered.
2217                     std::vector<VkSampleLocationEXT> sampleLocations(m_data.samples, {0.5f, 0.5f});
2218                     const VkSampleLocationsInfoEXT sampleLocationsInfo = {
2219                         VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, // VkStructureType sType;
2220                         DE_NULL,                                     // const void* pNext;
2221                         (VkSampleCountFlagBits)m_data.samples,       // VkSampleCountFlagBits sampleLocationsPerPixel;
2222                         {1, 1},                                      // VkExtent2D sampleLocationGridSize;
2223                         (uint32_t)m_data.samples,                    // uint32_t sampleLocationsCount;
2224                         &sampleLocations[0],                         // const VkSampleLocationEXT* pSampleLocations;
2225                     };
2226 
2227                     const VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo = {
2228                         VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT, // VkStructureType sType;
2229                         DE_NULL,                                                           // const void* pNext;
2230                         VK_TRUE,             // VkBool32 sampleLocationsEnable;
2231                         sampleLocationsInfo, // VkSampleLocationsInfoEXT sampleLocationsInfo;
2232                     };
2233 
2234                     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
2235                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                            sType
2236                         m_data.sampleLocations ? &pipelineSampleLocationsCreateInfo :
2237                                                  DE_NULL, // const void*                    pNext
2238                         0u,                               // VkPipelineMultisampleStateCreateFlags    flags
2239                         (VkSampleCountFlagBits)
2240                             m_data.samples, // VkSampleCountFlagBits                    rasterizationSamples
2241                         (VkBool32)m_data
2242                             .sampleShadingEnable, // VkBool32                                    sampleShadingEnable
2243                         1.0f,                     // float                                    minSampleShading
2244                         pSampleMask,              // const VkSampleMask*                        pSampleMask
2245                         VK_FALSE,                 // VkBool32                                    alphaToCoverageEnable
2246                         VK_FALSE                  // VkBool32                                    alphaToOneEnable
2247                     };
2248 
2249                     std::vector<VkViewport> viewports;
2250                     std::vector<VkRect2D> scissors;
2251                     if (m_data.multiViewport)
2252                     {
2253                         // Split the viewport into left and right halves
2254                         int x0 = 0, x1 = m_data.framebufferDim.width / 2, x2 = m_data.framebufferDim.width;
2255 
2256                         viewports.push_back(makeViewport((float)x0, 0, std::max((float)(x1 - x0), 1.0f),
2257                                                          (float)m_data.framebufferDim.height, 0.0f, 1.0f));
2258                         scissors.push_back(makeRect2D(x0, 0, x1 - x0, m_data.framebufferDim.height));
2259 
2260                         viewports.push_back(makeViewport((float)x1, 0, std::max((float)(x2 - x1), 1.0f),
2261                                                          (float)m_data.framebufferDim.height, 0.0f, 1.0f));
2262                         scissors.push_back(makeRect2D(x1, 0, x2 - x1, m_data.framebufferDim.height));
2263                     }
2264                     else
2265                     {
2266                         viewports.push_back(makeViewport(m_data.framebufferDim.width, m_data.framebufferDim.height));
2267                         scissors.push_back(makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height));
2268                     }
2269 
2270                     const auto &binaries     = m_context.getBinaryCollection();
2271                     ShaderWrapper fragShader = ShaderWrapper(vk, device, binaries.get("frag"), 0);
2272                     ShaderWrapper vertShader;
2273                     ShaderWrapper geomShader;
2274                     ShaderWrapper meshShader;
2275 
2276                     if (m_data.meshShader)
2277                     {
2278                         meshShader = ShaderWrapper(vk, device, binaries.get("mesh"), 0);
2279                     }
2280                     else
2281                     {
2282                         if (m_context.contextSupports(VK_API_VERSION_1_2))
2283                             vertShader = ShaderWrapper(vk, device, binaries.get("vert_1_2"), 0);
2284                         else
2285                             vertShader = ShaderWrapper(vk, device, binaries.get("vert"), 0);
2286 
2287                         if (m_data.geometryShader)
2288                             geomShader = ShaderWrapper(vk, device, binaries.get("geom"), 0);
2289                     }
2290 
2291                     const uint32_t fragSizeWH = m_data.sampleMaskTest ? 2 : 1;
2292 
2293                     PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
2294 #ifndef CTS_USES_VULKANSC
2295                     VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
2296                         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
2297                         DE_NULL,
2298                         m_data.multiView ? 0x3 : 0u,
2299                         1u,
2300                         &cbFormat,
2301                         dsFormat,
2302                         dsFormat};
2303                     renderingCreateInfoWrapper.ptr =
2304                         m_data.groupParams->useDynamicRendering ? &renderingCreateInfo : DE_NULL;
2305 #endif // CTS_USES_VULKANSC
2306 
2307                     VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo{
2308                         VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
2309                         renderingCreateInfoWrapper.ptr,                                         // const void* pNext;
2310                         {fragSizeWH, fragSizeWH}, // VkExtent2D fragmentSize;
2311                         {m_data.combinerOp[0],
2312                          m_data.combinerOp[1]}, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
2313                     };
2314 
2315                     VkDynamicState dynamicState = VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR;
2316                     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{
2317                         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
2318                         DE_NULL,                                              // const void* pNext;
2319                         (VkPipelineDynamicStateCreateFlags)0, // VkPipelineDynamicStateCreateFlags flags;
2320                         m_data.useDynamicState ? 1u : 0u,     // uint32_t dynamicStateCount;
2321                         &dynamicState,                        // const VkDynamicState* pDynamicStates;
2322                     };
2323 
2324                     // Enable depth/stencil writes, always passing
2325                     VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
2326                         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
2327                         DE_NULL,                                                    // const void* pNext;
2328                         0u,                   // VkPipelineDepthStencilStateCreateFlags flags;
2329                         VK_TRUE,              // VkBool32 depthTestEnable;
2330                         VK_TRUE,              // VkBool32 depthWriteEnable;
2331                         VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
2332                         VK_FALSE,             // VkBool32 depthBoundsTestEnable;
2333                         VK_TRUE,              // VkBool32 stencilTestEnable;
2334                         // VkStencilOpState front;
2335                         {
2336                             VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
2337                             VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
2338                             VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
2339                             VK_COMPARE_OP_ALWAYS,  // VkCompareOp compareOp;
2340                             0u,                    // uint32_t compareMask;
2341                             0xFFu,                 // uint32_t writeMask;
2342                             0xFFu,                 // uint32_t reference;
2343                         },
2344                         // VkStencilOpState back;
2345                         {
2346                             VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
2347                             VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
2348                             VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
2349                             VK_COMPARE_OP_ALWAYS,  // VkCompareOp compareOp;
2350                             0u,                    // uint32_t compareMask;
2351                             0xFFu,                 // uint32_t writeMask;
2352                             0xFFu,                 // uint32_t reference;
2353                         },
2354                         0.0f, // float minDepthBounds;
2355                         0.0f, // float maxDepthBounds;
2356                     };
2357 
2358                     const VkQueue queue = m_context.getUniversalQueue();
2359                     Move<VkCommandPool> cmdPool =
2360                         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
2361                                           m_context.getUniversalQueueFamilyIndex());
2362                     Move<VkCommandBuffer> cmdBuffer =
2363                         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2364                     Move<VkCommandBuffer> secCmdBuffer;
2365                     VkClearValue clearColor        = makeClearValueColorU32(0, 0, 0, 0);
2366                     VkClearValue clearDepthStencil = makeClearValueDepthStencil(0.0, 0);
2367 
2368                     std::vector<GraphicsPipelineWrapper> pipelines;
2369                     uint32_t pipelineCount =
2370                         (m_data.useDynamicState ? 1u : NUM_TRIANGLES) + (m_data.multiSubpasses ? 1u : 0u);
2371                     pipelines.reserve(pipelineCount);
2372 
2373                     std::vector<VkDescriptorSet> descriptorSetsRaw;
2374 
2375                     descriptorSetsRaw.reserve(descriptorSets.size());
2376 
2377                     std::transform(begin(descriptorSets), end(descriptorSets), std::back_inserter(descriptorSetsRaw),
2378                                    [](const Move<VkDescriptorSet> &elem) { return elem.get(); });
2379 
2380 #ifndef CTS_USES_VULKANSC
2381                     const VkExtent2D srTexelSize{srTexelWidth, srTexelHeight};
2382                     if (m_data.groupParams->useSecondaryCmdBuffer)
2383                     {
2384                         secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2385 
2386                         // record secondary command buffer
2387                         if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2388                         {
2389                             beginSecondaryCmdBuffer(*secCmdBuffer, cbFormat, dsFormat,
2390                                                     VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
2391                             beginDynamicRender(*secCmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView,
2392                                                *dsImageView, clearColor, clearDepthStencil);
2393                         }
2394                         else
2395                             beginSecondaryCmdBuffer(*secCmdBuffer, cbFormat, dsFormat);
2396 
2397                         drawCommands(*secCmdBuffer, pipelines, viewports, scissors, pipelineLayout, *renderPass,
2398                                      &vertexInputStateCreateInfo, &dynamicStateCreateInfo,
2399                                      &rasterizationStateCreateInfo, &depthStencilStateParams,
2400                                      &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2401                                      renderingCreateInfoWrapper, vertShader, geomShader, meshShader, fragShader,
2402                                      descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2403 
2404                         if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2405                             endRendering(vk, *secCmdBuffer);
2406 
2407                         endCommandBuffer(vk, *secCmdBuffer);
2408 
2409                         // record primary command buffer
2410                         beginCommandBuffer(vk, *cmdBuffer, 0u);
2411 
2412                         preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), secCbImage.get(), derivImage.get(),
2413                                           derivNumLevels, srImage.get(), srLayout, srFillBuffer.get(), numSRLayers,
2414                                           srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2415                         if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2416                             beginDynamicRender(*cmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView,
2417                                                *dsImageView, clearColor, clearDepthStencil,
2418                                                VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
2419 
2420                         vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
2421 
2422                         if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2423                             endRendering(vk, *cmdBuffer);
2424                     }
2425                     else if (m_data.groupParams->useDynamicRendering)
2426                     {
2427                         beginCommandBuffer(vk, *cmdBuffer);
2428                         preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), secCbImage.get(), derivImage.get(),
2429                                           derivNumLevels, srImage.get(), srLayout, srFillBuffer.get(), numSRLayers,
2430                                           srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2431                         beginDynamicRender(*cmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView, *dsImageView,
2432                                            clearColor, clearDepthStencil);
2433                         drawCommands(*cmdBuffer, pipelines, viewports, scissors, pipelineLayout, *renderPass,
2434                                      &vertexInputStateCreateInfo, &dynamicStateCreateInfo,
2435                                      &rasterizationStateCreateInfo, &depthStencilStateParams,
2436                                      &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2437                                      renderingCreateInfoWrapper, vertShader, geomShader, meshShader, fragShader,
2438                                      descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2439                         endRendering(vk, *cmdBuffer);
2440                     }
2441 #endif // CTS_USES_VULKANSC
2442 
2443                     de::MovePtr<BufferWithMemory> secVertexBuf;
2444                     secVertexBuf = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
2445                         vk, device, allocator,
2446                         makeBufferCreateInfo(vertexBufferSize,
2447                                              VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
2448                         MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
2449 
2450                     vector<tcu::Vec4> vertices;
2451                     vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
2452                     vertices.push_back(tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f));
2453                     vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
2454                     vertices.push_back(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
2455 
2456                     const VkDeviceSize vertexBufferSize2 = vertices.size() * sizeof(vertices[0]);
2457 
2458                     float *vbuf2 = (float *)secVertexBuf->getAllocation().getHostPtr();
2459                     deMemcpy(vbuf2, &vertices[0], static_cast<std::size_t>(vertexBufferSize2));
2460                     flushAlloc(vk, device, secVertexBuf->getAllocation());
2461 
2462                     ShaderWrapper fragSimpleShader = ShaderWrapper(vk, device, binaries.get("frag_simple"), 0);
2463                     ShaderWrapper vertSimpleShader = ShaderWrapper(vk, device, binaries.get("vert_simple"), 0);
2464 
2465                     PipelineLayoutWrapper pipelineLayout1(m_data.groupParams->pipelineConstructionType, vk, device);
2466 
2467                     if (!m_data.groupParams->useDynamicRendering)
2468                     {
2469                         beginCommandBuffer(vk, *cmdBuffer);
2470                         preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), secCbImage.get(), derivImage.get(),
2471                                           derivNumLevels, srImage.get(), srLayout, srFillBuffer.get(), numSRLayers,
2472                                           srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2473 
2474                         beginLegacyRender(*cmdBuffer, renderPass, *srImageView, *cbImageView, *dsImageView,
2475                                           *secCbImageView, imagelessFB);
2476                         drawCommands(*cmdBuffer, pipelines, viewports, scissors, pipelineLayout, *renderPass,
2477                                      &vertexInputStateCreateInfo, &dynamicStateCreateInfo,
2478                                      &rasterizationStateCreateInfo, &depthStencilStateParams,
2479                                      &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2480                                      renderingCreateInfoWrapper, vertShader, geomShader, meshShader, fragShader,
2481                                      descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2482 
2483                         if (m_data.multiSubpasses)
2484                         {
2485                             drawCommandsOnNormalSubpass(*cmdBuffer, pipelines, viewports, scissors, pipelineLayout1,
2486                                                         renderPass, &rasterizationStateCreateInfo,
2487                                                         &depthStencilStateParams, &multisampleStateCreateInfo,
2488                                                         vertSimpleShader, fragSimpleShader, 1u, **secVertexBuf);
2489                         }
2490 
2491                         renderPass.end(vk, *cmdBuffer);
2492 
2493                         if (m_data.multiSubpasses)
2494                             copyImageToBufferOnNormalSubpass(*cmdBuffer, secCbImage.get(), secColorOutputBuffer.get(),
2495                                                              colorOutputBufferSize);
2496                     }
2497 
2498                     VkMemoryBarrier memBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL,
2499                                                VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
2500                                                    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2501                                                    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
2502                                                VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT};
2503                     vk.cmdPipelineBarrier(*cmdBuffer, allPipelineStages, allPipelineStages, 0, 1, &memBarrier, 0,
2504                                           DE_NULL, 0, DE_NULL);
2505 
2506                     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1,
2507                                              &mainDescriptorSet, 0u, DE_NULL);
2508                     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
2509 
2510                     // Copy color/depth/stencil buffers to buffer memory
2511                     vk.cmdDispatch(*cmdBuffer, m_data.framebufferDim.width, m_data.framebufferDim.height,
2512                                    m_data.numColorLayers);
2513 
2514                     memBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2515                     memBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2516                     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2517                                           0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2518 
2519                     endCommandBuffer(vk, *cmdBuffer);
2520 
2521                     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2522 
2523                     uint32_t *colorptr = (uint32_t *)colorOutputBuffer->getAllocation().getHostPtr();
2524                     invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
2525 
2526                     invalidateAlloc(vk, device, atomicBuffer->getAllocation());
2527 
2528                     float *depthptr       = DE_NULL;
2529                     uint32_t *stencilptr  = DE_NULL;
2530                     uint32_t *secColorPtr = nullptr;
2531 
2532                     if (m_data.useDepthStencil)
2533                     {
2534                         depthptr = (float *)depthOutputBuffer->getAllocation().getHostPtr();
2535                         invalidateAlloc(vk, device, depthOutputBuffer->getAllocation());
2536 
2537                         stencilptr = (uint32_t *)stencilOutputBuffer->getAllocation().getHostPtr();
2538                         invalidateAlloc(vk, device, stencilOutputBuffer->getAllocation());
2539                     }
2540 
2541                     if (m_data.multiSubpasses)
2542                     {
2543                         secColorPtr = (uint32_t *)secColorOutputBuffer->getAllocation().getHostPtr();
2544                         invalidateAlloc(vk, device, secColorOutputBuffer->getAllocation());
2545                     }
2546 
2547                     // Loop over all samples and validate the output
2548                     for (uint32_t layer = 0; layer < m_data.numColorLayers && res == QP_TEST_RESULT_PASS; ++layer)
2549                     {
2550                         for (uint32_t y = 0; y < m_data.framebufferDim.height && res == QP_TEST_RESULT_PASS; ++y)
2551                         {
2552                             for (uint32_t x = 0; x < m_data.framebufferDim.width && res == QP_TEST_RESULT_PASS; ++x)
2553                             {
2554                                 for (int32_t s = 0; s < m_data.samples && res == QP_TEST_RESULT_PASS; ++s)
2555                                 {
2556                                     uint32_t *sample = &colorptr[4 * (((layer * m_data.framebufferDim.height + y) *
2557                                                                            m_data.framebufferDim.width +
2558                                                                        x) *
2559                                                                           m_data.samples +
2560                                                                       s)];
2561 
2562                                     // If testing the rasterizer sample mask, if this sample is not set in the
2563                                     // mask then it shouldn't have written anything.
2564                                     if (m_data.useApiSampleMask && !(sampleMask & (1 << s)) && sample[2] != 0)
2565                                     {
2566                                         log << tcu::TestLog::Message << std::hex
2567                                             << "sample written despite pSampleMask (" << x << "," << y << ",sample "
2568                                             << s << ")" << tcu::TestLog::EndMessage;
2569                                         res = QP_TEST_RESULT_FAIL;
2570                                         continue;
2571                                     }
2572 
2573                                     // The same isn't covered by any primitives, skip it
2574                                     if (sample[2] == 0)
2575                                         continue;
2576 
2577                                     // skip samples that have the same value as sample zero - it would be redundant to check them.
2578                                     if (s > 0)
2579                                     {
2580                                         uint32_t *sample0 = &colorptr[4 * (((layer * m_data.framebufferDim.height + y) *
2581                                                                                 m_data.framebufferDim.width +
2582                                                                             x) *
2583                                                                                m_data.samples +
2584                                                                            0)];
2585                                         bool same         = deMemCmp(sample, sample0, 16) == 0;
2586 
2587                                         if (m_data.fragDepth && !m_data.multiSubpasses)
2588                                         {
2589                                             float *dsample  = &depthptr[((layer * m_data.framebufferDim.height + y) *
2590                                                                             m_data.framebufferDim.width +
2591                                                                         x) *
2592                                                                            m_data.samples +
2593                                                                        s];
2594                                             float *dsample0 = &depthptr[((layer * m_data.framebufferDim.height + y) *
2595                                                                              m_data.framebufferDim.width +
2596                                                                          x) *
2597                                                                             m_data.samples +
2598                                                                         0];
2599                                             same            = same && (*dsample == *dsample0);
2600                                         }
2601 
2602                                         if (m_data.fragStencil && !m_data.multiSubpasses)
2603                                         {
2604                                             uint32_t *ssample =
2605                                                 &stencilptr[((layer * m_data.framebufferDim.height + y) *
2606                                                                  m_data.framebufferDim.width +
2607                                                              x) *
2608                                                                 m_data.samples +
2609                                                             s];
2610                                             uint32_t *ssample0 =
2611                                                 &stencilptr[((layer * m_data.framebufferDim.height + y) *
2612                                                                  m_data.framebufferDim.width +
2613                                                              x) *
2614                                                                 m_data.samples +
2615                                                             0];
2616                                             same = same && (*ssample == *ssample0);
2617                                         }
2618 
2619                                         if (same)
2620                                             continue;
2621                                     }
2622 
2623                                     // Fragment shader writes error codes to .w component.
2624                                     // All nonzero values are unconditionally failures
2625                                     if (sample[3] != 0)
2626                                     {
2627                                         if (sample[3] == ERROR_FRAGCOORD_CENTER)
2628                                             log << tcu::TestLog::Message << std::hex
2629                                                 << "fragcoord test failed pixel (0x" << x << ",0x" << y << ",sample 0x"
2630                                                 << s << ")" << tcu::TestLog::EndMessage;
2631                                         else if (sample[3] == ERROR_VTG_READBACK)
2632                                             log << tcu::TestLog::Message << std::hex
2633                                                 << "vs/gs output readback test failed pixel (0x" << x << ",0x" << y
2634                                                 << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2635                                         else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_DERIV)
2636                                             log << tcu::TestLog::Message << std::hex
2637                                                 << "fragcoord derivative test failed pixel (0x" << x << ",0x" << y
2638                                                 << ",sample 0x" << s
2639                                                 << ")="
2640                                                    "(0x"
2641                                                 << ((sample[3] >> 8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F)
2642                                                 << "), expected="
2643                                                    "(0x"
2644                                                 << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F)
2645                                                 << ")" << tcu::TestLog::EndMessage;
2646                                         else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_IMPLICIT_DERIV)
2647                                             log << tcu::TestLog::Message << std::hex
2648                                                 << "implicit derivative test failed pixel (0x" << x << ",0x" << y
2649                                                 << ",sample 0x" << s
2650                                                 << ")="
2651                                                    "(0x"
2652                                                 << ((sample[3] >> 8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F)
2653                                                 << "), expected="
2654                                                    "(0x"
2655                                                 << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F)
2656                                                 << ")" << tcu::TestLog::EndMessage;
2657                                         else
2658                                             log << tcu::TestLog::Message << std::hex
2659                                                 << "w coord unknown test failed pixel (0x" << x << ",0x" << y
2660                                                 << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2661                                         res = QP_TEST_RESULT_FAIL;
2662                                         continue;
2663                                     }
2664 
2665                                     // x component of sample
2666                                     uint32_t rate = sample[0];
2667                                     // fragment size
2668                                     uint32_t pixelsX = 1 << ((rate / 4) & 3);
2669                                     uint32_t pixelsY = 1 << (rate & 3);
2670 
2671                                     // Fragment region
2672                                     uint32_t fragMinX = x & ~(pixelsX - 1);
2673                                     uint32_t fragMinY = y & ~(pixelsY - 1);
2674                                     uint32_t fragMaxX = fragMinX + pixelsX;
2675                                     uint32_t fragMaxY = fragMinY + pixelsY;
2676 
2677                                     // Clamp to FB dimension for odd sizes
2678                                     if (fragMaxX > m_data.framebufferDim.width)
2679                                         fragMaxX = m_data.framebufferDim.width;
2680                                     if (fragMaxY > m_data.framebufferDim.height)
2681                                         fragMaxY = m_data.framebufferDim.height;
2682 
2683                                     // z component of sample
2684                                     uint32_t primID  = sample[2] >> 24;
2685                                     uint32_t atomVal = sample[2] & 0xFFFFFF;
2686 
2687                                     // Compute pipeline and primitive rate from primitive ID, and attachment
2688                                     // rate from the x/y coordinate
2689                                     int32_t pipelineRate = PrimIDToPipelineShadingRate(primID);
2690                                     int32_t primitiveRate =
2691                                         m_data.shaderWritesRate ? PrimIDToPrimitiveShadingRate(primID) : 0;
2692 
2693                                     int32_t attachmentLayer =
2694                                         (m_data.srLayered && modeIdx == ATTACHMENT_MODE_2DARRAY) ? layer : 0;
2695                                     int32_t attachmentRate =
2696                                         m_data.useAttachment() ?
2697                                             fillPtr[srFillBpp *
2698                                                     ((attachmentLayer * srHeight + (y / srTexelHeight)) * srWidth +
2699                                                      (x / srTexelWidth))] :
2700                                             0;
2701 
2702                                     // Get mask of allowed shading rates
2703                                     int32_t expectedMasks = Simulate(pipelineRate, primitiveRate, attachmentRate);
2704 
2705                                     if (!(expectedMasks & (1 << rate)))
2706                                     {
2707                                         log << tcu::TestLog::Message << std::hex
2708                                             << "unexpected shading rate. failed pixel (0x" << x << ",0x" << y
2709                                             << ",sample 0x" << s
2710                                             << ") "
2711                                                "result rate 0x"
2712                                             << rate << " mask of expected rates 0x" << expectedMasks
2713                                             << " pipelineRate=0x" << pipelineRate << " primitiveRate=0x"
2714                                             << primitiveRate << " attachmentRate =0x" << attachmentRate
2715                                             << tcu::TestLog::EndMessage;
2716                                         res = QP_TEST_RESULT_FAIL;
2717                                         continue;
2718                                     }
2719                                     // Check that not all fragments are downgraded to 1x1
2720                                     if (rate == 0 && expectedMasks != 1)
2721                                         numUnexpected1x1Samples++;
2722                                     numTotalSamples++;
2723 
2724                                     // Check that gl_FragDepth = primID / NUM_TRIANGLES
2725                                     if (m_data.fragDepth && !m_data.multiSubpasses)
2726                                     {
2727                                         float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) *
2728                                                                         m_data.framebufferDim.width +
2729                                                                     x) *
2730                                                                        m_data.samples +
2731                                                                    s];
2732                                         float expected = (float)primID / NUM_TRIANGLES;
2733                                         if (fabs(*dsample - expected) > 0.01)
2734                                         {
2735                                             log << tcu::TestLog::Message << std::hex << "depth write failed pixel (0x"
2736                                                 << x << ",0x" << y << ",sample 0x" << s << ")=" << *dsample
2737                                                 << " expected " << expected << tcu::TestLog::EndMessage;
2738                                             res = QP_TEST_RESULT_FAIL;
2739                                             continue;
2740                                         }
2741                                     }
2742 
2743                                     // Check that stencil value = primID
2744                                     if (m_data.fragStencil && !m_data.multiSubpasses)
2745                                     {
2746                                         uint32_t *ssample = &stencilptr[((layer * m_data.framebufferDim.height + y) *
2747                                                                              m_data.framebufferDim.width +
2748                                                                          x) *
2749                                                                             m_data.samples +
2750                                                                         s];
2751                                         if (*ssample != primID)
2752                                         {
2753                                             log << tcu::TestLog::Message << std::hex << "stencil write failed pixel (0x"
2754                                                 << x << ",0x" << y << ",sample 0x" << s << ")=" << *ssample
2755                                                 << " expected " << primID << tcu::TestLog::EndMessage;
2756                                             res = QP_TEST_RESULT_FAIL;
2757                                             continue;
2758                                         }
2759                                     }
2760 
2761                                     // Check that primitives are in the right viewport/scissor
2762                                     if (m_data.multiViewport)
2763                                     {
2764                                         VkRect2D *scissor = &scissors[primID & 1];
2765                                         if ((int)x < scissor->offset.x ||
2766                                             (int)x >= (int)(scissor->offset.x + scissor->extent.width) ||
2767                                             (int)y < scissor->offset.y ||
2768                                             (int)y >= (int)(scissor->offset.y + scissor->extent.height))
2769                                         {
2770                                             log << tcu::TestLog::Message << std::hex
2771                                                 << "primitive found outside of expected viewport (0x" << x << ",0x" << y
2772                                                 << ",sample 0x" << s << ") primID=" << primID
2773                                                 << tcu::TestLog::EndMessage;
2774                                             res = QP_TEST_RESULT_FAIL;
2775                                             continue;
2776                                         }
2777                                     }
2778 
2779                                     // Check that primitives are in the right layer
2780                                     if (m_data.colorLayered)
2781                                     {
2782                                         if (layer != ((primID & 2) >> 1))
2783                                         {
2784                                             log << tcu::TestLog::Message << std::hex
2785                                                 << "primitive found in wrong layer (0x" << x << ",0x" << y
2786                                                 << ",sample 0x" << s << ") primID=" << primID << " layer=" << layer
2787                                                 << tcu::TestLog::EndMessage;
2788                                             res = QP_TEST_RESULT_FAIL;
2789                                             continue;
2790                                         }
2791                                     }
2792 
2793                                     // Check that multiview broadcasts the same primitive to both layers
2794                                     if (m_data.multiView)
2795                                     {
2796                                         uint32_t otherLayer = layer ^ 1;
2797                                         uint32_t *othersample =
2798                                             &colorptr[4 * (((otherLayer * m_data.framebufferDim.height + y) *
2799                                                                 m_data.framebufferDim.width +
2800                                                             x) *
2801                                                                m_data.samples +
2802                                                            s)];
2803                                         uint32_t otherPrimID = othersample[2] >> 24;
2804                                         if (primID != otherPrimID)
2805                                         {
2806                                             log << tcu::TestLog::Message << std::hex
2807                                                 << "multiview primitive mismatch (0x" << x << ",0x" << y << ",sample 0x"
2808                                                 << s << ") primID=" << primID << "  otherPrimID=" << otherPrimID
2809                                                 << tcu::TestLog::EndMessage;
2810                                             res = QP_TEST_RESULT_FAIL;
2811                                             continue;
2812                                         }
2813                                     }
2814 
2815                                     // Loop over all samples in the same fragment
2816                                     for (uint32_t fx = fragMinX; fx < fragMaxX; ++fx)
2817                                     {
2818                                         for (uint32_t fy = fragMinY; fy < fragMaxY; ++fy)
2819                                         {
2820                                             for (int32_t fs = 0; fs < m_data.samples; ++fs)
2821                                             {
2822                                                 uint32_t *fsample =
2823                                                     &colorptr[4 * (((layer * m_data.framebufferDim.height + fy) *
2824                                                                         m_data.framebufferDim.width +
2825                                                                     fx) *
2826                                                                        m_data.samples +
2827                                                                    fs)];
2828                                                 uint32_t frate    = fsample[0];
2829                                                 uint32_t fprimID  = fsample[2] >> 24;
2830                                                 uint32_t fatomVal = fsample[2] & 0xFFFFFF;
2831 
2832                                                 // If we write out the sample mask value, check that the samples in the
2833                                                 // mask must not be uncovered, and that samples not in the mask must not
2834                                                 // be covered by this primitive
2835                                                 if (m_data.useSampleMaskIn)
2836                                                 {
2837                                                     int p = pixelsX * pixelsY -
2838                                                             ((fx - fragMinX) + pixelsX * (fy - fragMinY)) - 1;
2839                                                     int sampleIdx = fs + m_data.samples * p;
2840 
2841                                                     if ((sample[1] & (1 << sampleIdx)) && fsample[2] == 0)
2842                                                     {
2843                                                         log << tcu::TestLog::Message << std::hex
2844                                                             << "sample set in sampleMask but not written (0x" << fx
2845                                                             << ",0x" << fy << ",sample 0x" << fs << ")"
2846                                                             << tcu::TestLog::EndMessage;
2847                                                         res = QP_TEST_RESULT_FAIL;
2848                                                         continue;
2849                                                     }
2850                                                     if (!(sample[1] & (1 << sampleIdx)) && fsample[2] != 0 &&
2851                                                         fprimID == primID)
2852                                                     {
2853                                                         log << tcu::TestLog::Message << std::hex
2854                                                             << "sample not set in sampleMask but written with same "
2855                                                                "primID (0x"
2856                                                             << fx << ",0x" << fy << ",sample 0x" << fs << ")"
2857                                                             << tcu::TestLog::EndMessage;
2858                                                         res = QP_TEST_RESULT_FAIL;
2859                                                         continue;
2860                                                     }
2861                                                 }
2862 
2863                                                 // If conservative raster is enabled, or custom sample locations all at the center, check that
2864                                                 // samples in the same pixel must be covered.
2865                                                 if (m_data.conservativeEnable ||
2866                                                     (m_data.sampleLocations &&
2867                                                      m_context.getFragmentShadingRateProperties()
2868                                                          .fragmentShadingRateWithCustomSampleLocations))
2869                                                 {
2870                                                     // If it's in the same pixel, expect it to be fully covered.
2871                                                     if (fx == x && fy == y && fsample[2] == 0)
2872                                                     {
2873                                                         log << tcu::TestLog::Message << std::hex
2874                                                             << "pixel not fully covered (0x" << fx << ",0x" << fy
2875                                                             << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2876                                                         res = QP_TEST_RESULT_FAIL;
2877                                                         continue;
2878                                                     }
2879                                                 }
2880 
2881                                                 if (fsample[2] == 0)
2882                                                     continue;
2883 
2884                                                 // If the primitive matches this sample, then it must have the same rate and
2885                                                 // atomic value
2886                                                 if (fprimID == primID)
2887                                                 {
2888                                                     if (rate != frate ||
2889                                                         (atomVal != fatomVal &&
2890                                                          !(m_data.sampleShadingEnable || m_data.sampleShadingInput)))
2891                                                     {
2892                                                         log << tcu::TestLog::Message << std::hex << "failed pixel (0x"
2893                                                             << x << ",0x" << y << ",sample " << s << ")=0x"
2894                                                             << ((primID << 24) | atomVal) << " compared to (0x" << fx
2895                                                             << ",0x" << fy << ",sample " << fs << ")=0x"
2896                                                             << ((fprimID << 24) | fatomVal) << " pipelineRate=0x"
2897                                                             << pipelineRate << " primitiveRate=0x" << primitiveRate
2898                                                             << " attachmentRate =0x" << attachmentRate
2899                                                             << tcu::TestLog::EndMessage;
2900                                                         res = QP_TEST_RESULT_FAIL;
2901                                                     }
2902                                                 }
2903                                             }
2904                                         }
2905                                     }
2906                                 }
2907                             }
2908                         }
2909                     }
2910 
2911                     if (res == QP_TEST_RESULT_FAIL)
2912                         break;
2913 
2914                     if (secColorPtr)
2915                     {
2916                         const tcu::TextureFormat format = mapVkFormat(cbFormat);
2917                         const tcu::ConstPixelBufferAccess resultImage(format, m_data.framebufferDim.width,
2918                                                                       m_data.framebufferDim.height, 1, secColorPtr);
2919 
2920                         tcu::TextureLevel textureLevel(format, m_data.framebufferDim.width,
2921                                                        m_data.framebufferDim.height, 1);
2922                         const tcu::PixelBufferAccess expectedImage(textureLevel);
2923 
2924                         for (int z = 0; z < expectedImage.getDepth(); ++z)
2925                         {
2926                             for (int y = 0; y < expectedImage.getHeight(); ++y)
2927                             {
2928                                 for (int x = 0; x < expectedImage.getWidth(); ++x)
2929                                     expectedImage.setPixel(tcu::UVec4(128, 128, 128, 1), x, y, z);
2930                             }
2931                         }
2932 
2933                         if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image Comparison", "",
2934                                                       expectedImage, resultImage, tcu::UVec4(1),
2935                                                       tcu::COMPARE_LOG_RESULT))
2936                             return tcu::TestStatus::fail("Fail");
2937 
2938                         for (uint32_t y = 0; y < m_data.framebufferDim.height && res == QP_TEST_RESULT_PASS; ++y)
2939                         {
2940                             for (uint32_t x = 0; x < m_data.framebufferDim.width && res == QP_TEST_RESULT_PASS; ++x)
2941                             {
2942                                 if (m_data.fragDepth)
2943                                 {
2944                                     float *dsample = &depthptr[(y * m_data.framebufferDim.width + x)];
2945                                     if (*dsample != 0.4f)
2946                                     {
2947                                         log << tcu::TestLog::Message << std::hex
2948                                             << "On another subpass, depth write failed pixel (0x" << x << ",0x" << y
2949                                             << ",sample 0x1"
2950                                             << ")=" << *dsample << " expected 0.4f" << tcu::TestLog::EndMessage;
2951                                         res = QP_TEST_RESULT_FAIL;
2952                                         continue;
2953                                     }
2954                                 }
2955                                 if (m_data.fragStencil)
2956                                 {
2957                                     uint32_t *ssample = &stencilptr[y * m_data.framebufferDim.width + x];
2958                                     if (*ssample != 1)
2959                                     {
2960                                         log << tcu::TestLog::Message << std::hex
2961                                             << "On another subpass, stencil write failed pixel (0x" << x << ",0x" << y
2962                                             << ",sample 0x1"
2963                                             << ")=" << *ssample << " expected 1" << tcu::TestLog::EndMessage;
2964                                         res = QP_TEST_RESULT_FAIL;
2965                                         continue;
2966                                     }
2967                                 }
2968                             }
2969                         }
2970                     }
2971 
2972                     if (res == QP_TEST_RESULT_FAIL)
2973                         break;
2974                 }
2975     }
2976     // All samples were coerced to 1x1, unexpected
2977     if (res == QP_TEST_RESULT_PASS && numTotalSamples != 0 && numUnexpected1x1Samples == numTotalSamples &&
2978         numTotalSamples > 16)
2979     {
2980         log << tcu::TestLog::Message << std::hex << "Quality warning - all fragments used 1x1"
2981             << tcu::TestLog::EndMessage;
2982         res = QP_TEST_RESULT_QUALITY_WARNING;
2983     }
2984 
2985     return tcu::TestStatus(res, qpGetTestResultName(res));
2986 }
2987 
2988 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat cbFormat,VkFormat dsFormat,VkRenderingFlagsKHR renderingFlags) const2989 void FSRTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat cbFormat, VkFormat dsFormat,
2990                                               VkRenderingFlagsKHR renderingFlags) const
2991 {
2992     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
2993         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
2994         DE_NULL,                                                         // const void* pNext;
2995         renderingFlags,                                                  // VkRenderingFlagsKHR flags;
2996         m_data.multiView ? 0x3 : 0u,                                     // uint32_t viewMask;
2997         1u,                                                              // uint32_t colorAttachmentCount;
2998         &cbFormat,                                                       // const VkFormat* pColorAttachmentFormats;
2999         dsFormat,                                                        // VkFormat depthAttachmentFormat;
3000         dsFormat,                                                        // VkFormat stencilAttachmentFormat;
3001         m_data.samples,                                                  // VkSampleCountFlagBits rasterizationSamples;
3002     };
3003     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
3004 
3005     VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
3006     if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
3007         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
3008 
3009     const VkCommandBufferBeginInfo commandBufBeginParams{
3010         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
3011         DE_NULL,                                     // const void* pNext;
3012         usageFlags,                                  // VkCommandBufferUsageFlags flags;
3013         &bufferInheritanceInfo};
3014 
3015     const DeviceInterface &vk = m_context.getDeviceInterface();
3016     VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
3017 }
3018 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkImageView srImageView,VkImageLayout srImageLayout,const VkExtent2D & srTexelSize,VkImageView cbImageView,VkImageView dsImageView,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil,VkRenderingFlagsKHR renderingFlags) const3019 void FSRTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkImageView srImageView,
3020                                          VkImageLayout srImageLayout, const VkExtent2D &srTexelSize,
3021                                          VkImageView cbImageView, VkImageView dsImageView,
3022                                          const VkClearValue &clearColor, const VkClearValue &clearDepthStencil,
3023                                          VkRenderingFlagsKHR renderingFlags) const
3024 {
3025     const DeviceInterface &vk = m_context.getDeviceInterface();
3026     VkRect2D renderArea       = makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
3027 
3028     VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo{
3029         VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType sType;
3030         DE_NULL,                                                               // const void* pNext;
3031         m_data.useAttachment() ? srImageView : DE_NULL,                        // VkImageView imageView;
3032         srImageLayout,                                                         // VkImageLayout imageLayout;
3033         srTexelSize // VkExtent2D shadingRateAttachmentTexelSize;
3034     };
3035 
3036     VkRenderingAttachmentInfoKHR colorAttachment{
3037         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
3038         DE_NULL,                                             // const void* pNext;
3039         cbImageView,                                         // VkImageView imageView;
3040         VK_IMAGE_LAYOUT_GENERAL,                             // VkImageLayout imageLayout;
3041         VK_RESOLVE_MODE_NONE,                                // VkResolveModeFlagBits resolveMode;
3042         DE_NULL,                                             // VkImageView resolveImageView;
3043         VK_IMAGE_LAYOUT_UNDEFINED,                           // VkImageLayout resolveImageLayout;
3044         VK_ATTACHMENT_LOAD_OP_LOAD,                          // VkAttachmentLoadOp loadOp;
3045         VK_ATTACHMENT_STORE_OP_STORE,                        // VkAttachmentStoreOp storeOp;
3046         clearColor                                           // VkClearValue clearValue;
3047     };
3048 
3049     std::vector<VkRenderingAttachmentInfoKHR> depthStencilAttachments(
3050         2,
3051         {
3052             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
3053             DE_NULL,                                         // const void* pNext;
3054             dsImageView,                                     // VkImageView imageView;
3055             VK_IMAGE_LAYOUT_GENERAL,                         // VkImageLayout imageLayout;
3056             VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
3057             DE_NULL,                                         // VkImageView resolveImageView;
3058             VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
3059             VK_ATTACHMENT_LOAD_OP_LOAD,                      // VkAttachmentLoadOp loadOp;
3060             VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
3061             clearDepthStencil                                // VkClearValue clearValue;
3062         });
3063 
3064     vk::VkRenderingInfoKHR renderingInfo{
3065         vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
3066         m_data.useAttachment() || m_data.useAttachmentWithoutImageView() ? &shadingRateAttachmentInfo : DE_NULL,
3067         renderingFlags,                               // VkRenderingFlagsKHR flags;
3068         renderArea,                                   // VkRect2D renderArea;
3069         m_data.multiView ? 1 : m_data.numColorLayers, // uint32_t layerCount;
3070         m_data.multiView ? 0x3 : 0u,                  // uint32_t viewMask;
3071         1u,                                           // uint32_t colorAttachmentCount;
3072         &colorAttachment,                             // const VkRenderingAttachmentInfoKHR* pColorAttachments;
3073         m_data.useDepthStencil ? &depthStencilAttachments[0] :
3074                                  DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
3075         m_data.useDepthStencil ? &depthStencilAttachments[1] :
3076                                  DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
3077     };
3078 
3079     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
3080 }
3081 #endif // CTS_USES_VULKANSC
3082 
preRenderCommands(VkCommandBuffer cmdBuffer,ImageWithMemory * cbImage,ImageWithMemory * dsImage,ImageWithMemory * secCbImage,ImageWithMemory * derivImage,uint32_t derivNumLevels,ImageWithMemory * srImage,VkImageLayout srLayout,BufferWithMemory * srFillBuffer,uint32_t numSRLayers,uint32_t srWidth,uint32_t srHeight,uint32_t srFillBpp,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil)3083 void FSRTestInstance::preRenderCommands(VkCommandBuffer cmdBuffer, ImageWithMemory *cbImage, ImageWithMemory *dsImage,
3084                                         ImageWithMemory *secCbImage, ImageWithMemory *derivImage,
3085                                         uint32_t derivNumLevels, ImageWithMemory *srImage, VkImageLayout srLayout,
3086                                         BufferWithMemory *srFillBuffer, uint32_t numSRLayers, uint32_t srWidth,
3087                                         uint32_t srHeight, uint32_t srFillBpp, const VkClearValue &clearColor,
3088                                         const VkClearValue &clearDepthStencil)
3089 {
3090     const DeviceInterface &vk = m_context.getDeviceInterface();
3091     const VkDevice device     = m_context.getDevice();
3092 
3093     VkFlags allPipelineStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
3094                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
3095                                 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
3096                                 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
3097                                 VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
3098 
3099     if (m_data.geometryShader)
3100         allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
3101 
3102     VkImageMemoryBarrier imageBarrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
3103                                       DE_NULL,                                // const void*            pNext
3104                                       0u,                                     // VkAccessFlags        srcAccessMask
3105                                       VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags        dstAccessMask
3106                                       VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout        oldLayout
3107                                       VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout        newLayout
3108                                       VK_QUEUE_FAMILY_IGNORED, // uint32_t                srcQueueFamilyIndex
3109                                       VK_QUEUE_FAMILY_IGNORED, // uint32_t                dstQueueFamilyIndex
3110                                       cbImage->get(),          // VkImage                image
3111                                       {
3112                                           VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
3113                                           0u,                        // uint32_t                baseMipLevel
3114                                           VK_REMAINING_MIP_LEVELS,   // uint32_t                mipLevels,
3115                                           0u,                        // uint32_t                baseArray
3116                                           VK_REMAINING_ARRAY_LAYERS, // uint32_t                arraySize
3117                                       }};
3118 
3119     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3120                           (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3121                           (const VkBufferMemoryBarrier *)DE_NULL, 1, &imageBarrier);
3122 
3123     imageBarrier.image     = derivImage->get();
3124     imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3125 
3126     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3127                           (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3128                           (const VkBufferMemoryBarrier *)DE_NULL, 1, &imageBarrier);
3129 
3130     // Clear level to 1<<level
3131     for (uint32_t i = 0; i < derivNumLevels; ++i)
3132     {
3133         VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, i, 1u, 0u, 1u);
3134         VkClearValue clearLevelColor  = makeClearValueColorU32(1 << i, 0, 0, 0);
3135         vk.cmdClearColorImage(cmdBuffer, derivImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearLevelColor.color, 1, &range);
3136     }
3137 
3138     // Clear color buffer to transparent black
3139     {
3140         VkImageSubresourceRange range =
3141             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
3142         vk.cmdClearColorImage(cmdBuffer, cbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
3143     }
3144 
3145     // Clear the second color buffer to transparent black
3146     if (m_data.multiSubpasses)
3147     {
3148         VkImageSubresourceRange range = makeImageSubresourceRange(
3149             VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
3150 
3151         imageBarrier.image            = secCbImage->get();
3152         imageBarrier.newLayout        = VK_IMAGE_LAYOUT_GENERAL;
3153         imageBarrier.subresourceRange = range;
3154 
3155         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3156                               0u, // dependencyFlags
3157                               0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
3158 
3159         vk.cmdClearColorImage(cmdBuffer, secCbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
3160     }
3161 
3162     // Clear depth and stencil
3163     if (m_data.useDepthStencil)
3164     {
3165         VkImageSubresourceRange range =
3166             makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, m_data.dsBaseMipLevel,
3167                                       1u, 0u, VK_REMAINING_ARRAY_LAYERS);
3168         VkImageMemoryBarrier dsBarrier = imageBarrier;
3169         dsBarrier.image                = dsImage->get();
3170         dsBarrier.newLayout            = VK_IMAGE_LAYOUT_GENERAL;
3171         dsBarrier.subresourceRange     = range;
3172         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3173                               0u, // dependencyFlags
3174                               0u, nullptr, 0u, nullptr, 1u, &dsBarrier);
3175         if (!m_data.dsClearOp)
3176             vk.cmdClearDepthStencilImage(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_GENERAL,
3177                                          &clearDepthStencil.depthStencil, 1, &range);
3178     }
3179 
3180     // Initialize shading rate image with varying values
3181     if (m_data.useAttachment())
3182     {
3183         imageBarrier.image     = srImage->get();
3184         imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3185 
3186         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3187                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3188                               (const VkBufferMemoryBarrier *)DE_NULL, 1, &imageBarrier);
3189 
3190         uint8_t *fillPtr = (uint8_t *)srFillBuffer->getAllocation().getHostPtr();
3191         for (uint32_t layer = 0; layer < numSRLayers; ++layer)
3192         {
3193             for (uint32_t x = 0; x < srWidth; ++x)
3194             {
3195                 for (uint32_t y = 0; y < srHeight; ++y)
3196                 {
3197                     uint32_t idx = (layer * srHeight + y) * srWidth + x;
3198                     uint8_t val  = (uint8_t)SanitizeRate(idx & 0xF);
3199                     // actual shading rate is always in the LSBs of the first byte of a texel
3200                     fillPtr[srFillBpp * idx] = val;
3201                 }
3202             }
3203         }
3204         flushAlloc(vk, device, srFillBuffer->getAllocation());
3205 
3206         const VkBufferImageCopy copyRegion{
3207             0u, // VkDeviceSize bufferOffset;
3208             0u, // uint32_t bufferRowLength;
3209             0u, // uint32_t bufferImageHeight;
3210             {
3211                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
3212                 0u,                        // uint32_t mipLevel;
3213                 0u,                        // uint32_t baseArrayLayer;
3214                 numSRLayers,               // uint32_t layerCount;
3215             },                             // VkImageSubresourceLayers imageSubresource;
3216             {0, 0, 0},                     // VkOffset3D imageOffset;
3217             {srWidth, srHeight, 1},        // VkExtent3D imageExtent;
3218         };
3219 
3220         vk.cmdCopyBufferToImage(cmdBuffer, srFillBuffer->get(), srImage->get(), VK_IMAGE_LAYOUT_GENERAL, 1,
3221                                 &copyRegion);
3222 
3223         auto preShadingRateBarrier          = imageBarrier;
3224         preShadingRateBarrier.oldLayout     = VK_IMAGE_LAYOUT_GENERAL;
3225         preShadingRateBarrier.newLayout     = srLayout;
3226         preShadingRateBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3227         preShadingRateBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
3228 
3229         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
3230                               VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, (VkDependencyFlags)0, 0,
3231                               (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL, 1,
3232                               &preShadingRateBarrier);
3233     }
3234 
3235     VkMemoryBarrier memBarrier{
3236         VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
3237         DE_NULL,                          // pNext
3238         0u,                               // srcAccessMask
3239         0u,                               // dstAccessMask
3240     };
3241 
3242     memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3243     memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
3244                                VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR |
3245                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
3246                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
3247     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, allPipelineStages, 0, 1, &memBarrier, 0, DE_NULL,
3248                           0, DE_NULL);
3249 }
3250 
beginLegacyRender(VkCommandBuffer cmdBuffer,RenderPassWrapper & renderPass,VkImageView srImageView,VkImageView cbImageView,VkImageView dsImageView,VkImageView secCbImageView,bool imagelessFB) const3251 void FSRTestInstance::beginLegacyRender(VkCommandBuffer cmdBuffer, RenderPassWrapper &renderPass,
3252                                         VkImageView srImageView, VkImageView cbImageView, VkImageView dsImageView,
3253                                         VkImageView secCbImageView, bool imagelessFB) const
3254 {
3255     const DeviceInterface &vk = m_context.getDeviceInterface();
3256     VkRect2D renderArea       = makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
3257 
3258     std::vector<VkImageView> attachments = {cbImageView};
3259     if (m_data.useAttachment())
3260         attachments.push_back(srImageView);
3261     if (m_data.useDepthStencil)
3262         attachments.push_back(dsImageView);
3263     if (m_data.multiSubpasses)
3264         attachments.push_back(secCbImageView);
3265 
3266     const VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo{
3267         VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, // VkStructureType sType;
3268         DE_NULL,                                             // const void* pNext;
3269         (uint32_t)attachments.size(),                        // uint32_t attachmentCount;
3270         &attachments[0]                                      // const VkImageView* pAttachments;
3271     };
3272 
3273     std::vector<VkClearValue> clearVals;
3274 
3275     if (m_data.dsClearOp)
3276     {
3277         clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3278         if (m_data.useAttachment())
3279             clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3280         if (m_data.useDepthStencil)
3281             clearVals.push_back(makeClearValueDepthStencil(0.0f, 0));
3282         if (m_data.multiSubpasses)
3283             clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3284     }
3285 
3286     renderPass.begin(vk, cmdBuffer, renderArea, m_data.dsClearOp ? static_cast<uint32_t>(clearVals.size()) : 0,
3287                      m_data.dsClearOp ? clearVals.data() : nullptr, VK_SUBPASS_CONTENTS_INLINE,
3288                      imagelessFB ? &renderPassAttachmentBeginInfo : DE_NULL);
3289 }
3290 
drawCommandsOnNormalSubpass(VkCommandBuffer cmdBuffer,std::vector<GraphicsPipelineWrapper> & pipelines,const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & pipelineLayout,const RenderPassWrapper & renderPass,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const ShaderWrapper & vertShader,const ShaderWrapper & fragShader,const uint32_t subpass,VkBuffer vertexBuffer)3291 void FSRTestInstance::drawCommandsOnNormalSubpass(
3292     VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
3293     const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
3294     const PipelineLayoutWrapper &pipelineLayout, const RenderPassWrapper &renderPass,
3295     const VkPipelineRasterizationStateCreateInfo *rasterizationState,
3296     const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
3297     const VkPipelineMultisampleStateCreateInfo *multisampleState, const ShaderWrapper &vertShader,
3298     const ShaderWrapper &fragShader, const uint32_t subpass, VkBuffer vertexBuffer)
3299 {
3300     const InstanceInterface &vki          = m_context.getInstanceInterface();
3301     const DeviceInterface &vk             = m_context.getDeviceInterface();
3302     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3303     const VkDevice device                 = m_context.getDevice();
3304     const auto &deviceExtensions          = m_context.getDeviceExtensions();
3305 
3306     pipelines.emplace_back(vki, vk, physicalDevice, device, deviceExtensions,
3307                            m_data.groupParams->pipelineConstructionType);
3308     auto &pipeline = pipelines.back();
3309 
3310     pipeline.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP).setDefaultColorBlendState();
3311 
3312     pipeline.setupVertexInputState()
3313         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, subpass, vertShader,
3314                                           rasterizationState)
3315         .setupFragmentShaderState(pipelineLayout, *renderPass, subpass, fragShader, depthStencilState, multisampleState)
3316         .setupFragmentOutputState(*renderPass, subpass, nullptr, multisampleState)
3317         .setMonolithicPipelineLayout(pipelineLayout)
3318         .buildPipeline();
3319 
3320     const VkDeviceSize vertexBufferOffset = 0;
3321 
3322     vk.cmdNextSubpass(cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
3323     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3324     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
3325     vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
3326 }
3327 
copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer,const ImageWithMemory * image,const BufferWithMemory * outputBuffer,const VkDeviceSize bufferSize)3328 void FSRTestInstance::copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer, const ImageWithMemory *image,
3329                                                        const BufferWithMemory *outputBuffer,
3330                                                        const VkDeviceSize bufferSize)
3331 {
3332     const DeviceInterface &vk = m_context.getDeviceInterface();
3333 
3334     // Copy the image to output buffer.
3335     const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3336     const auto postImageBarrier = makeImageMemoryBarrier(
3337         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
3338         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->get(), subresourceRange);
3339     const auto bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
3340                                                        outputBuffer->get(), 0ull, bufferSize);
3341 
3342     const auto imageExtent = makeExtent3D(m_data.framebufferDim.width, m_data.framebufferDim.height, 1u);
3343     const auto copyRegion =
3344         makeBufferImageCopy(imageExtent, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
3345 
3346     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
3347                           0u, nullptr, 0u, nullptr, 1u, &postImageBarrier);
3348     vk.cmdCopyImageToBuffer(cmdBuffer, image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outputBuffer->get(), 1u,
3349                             &copyRegion);
3350     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u,
3351                           &bufferBarrier, 0u, nullptr);
3352 }
3353 
drawCommands(VkCommandBuffer cmdBuffer,std::vector<GraphicsPipelineWrapper> & pipelines,const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineDynamicStateCreateInfo * dynamicState,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,VkPipelineFragmentShadingRateStateCreateInfoKHR * shadingRateState,PipelineRenderingCreateInfoWrapper dynamicRenderingState,const ShaderWrapper vertShader,const ShaderWrapper geomShader,const ShaderWrapper meshShader,const ShaderWrapper fragShader,const std::vector<VkDescriptorSet> & descriptorSets,VkBuffer vertexBuffer,const uint32_t pushConstantSize)3354 void FSRTestInstance::drawCommands(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
3355                                    const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
3356                                    const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
3357                                    const VkPipelineVertexInputStateCreateInfo *vertexInputState,
3358                                    const VkPipelineDynamicStateCreateInfo *dynamicState,
3359                                    const VkPipelineRasterizationStateCreateInfo *rasterizationState,
3360                                    const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
3361                                    const VkPipelineMultisampleStateCreateInfo *multisampleState,
3362                                    VkPipelineFragmentShadingRateStateCreateInfoKHR *shadingRateState,
3363                                    PipelineRenderingCreateInfoWrapper dynamicRenderingState,
3364                                    const ShaderWrapper vertShader, const ShaderWrapper geomShader,
3365                                    const ShaderWrapper meshShader, const ShaderWrapper fragShader,
3366                                    const std::vector<VkDescriptorSet> &descriptorSets, VkBuffer vertexBuffer,
3367                                    const uint32_t pushConstantSize)
3368 {
3369     const InstanceInterface &vki          = m_context.getInstanceInterface();
3370     const DeviceInterface &vk             = m_context.getDeviceInterface();
3371     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3372     const VkDevice device                 = m_context.getDevice();
3373     const bool useMesh                    = (meshShader.isSet());
3374 
3375 #ifdef CTS_USES_VULKANSC
3376     if (useMesh)
3377         DE_ASSERT(false);
3378 #endif // CTS_USES_VULKANSC
3379 
3380     VkFlags allShaderStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
3381 
3382     if (useMesh)
3383     {
3384 #ifndef CTS_USES_VULKANSC
3385         allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
3386 #endif // CTS_USES_VULKANSC
3387     }
3388     else
3389     {
3390         allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
3391         if (m_data.geometryShader)
3392             allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
3393     }
3394 
3395     VkPipelineCreateFlags pipelineCreateFlags = (VkPipelineCreateFlags)0;
3396 
3397 #ifndef CTS_USES_VULKANSC
3398     if (m_data.groupParams->useDynamicRendering)
3399         pipelineCreateFlags |= VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
3400 #endif // CTS_USES_VULKANSC
3401 
3402     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0,
3403                              static_cast<uint32_t>(descriptorSets.size()), de::dataOrNull(descriptorSets), 0, DE_NULL);
3404 
3405     PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo = dynamicRenderingState;
3406 #ifndef CTS_USES_VULKANSC
3407     vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfoWithGarbage;
3408     std::vector<VkFormat> garbageFormats;
3409 
3410     if (m_data.garbageAttachment)
3411     {
3412         for (int i = 0; i < 10; i++)
3413             garbageFormats.push_back(VK_FORMAT_UNDEFINED);
3414 
3415         pipelineRenderingCreateInfoWithGarbage = *dynamicRenderingState.ptr;
3416         // Just set a bunch of VK_FORMAT_UNDEFINED for garbage_color_attachment tests to make the validation happy.
3417         pipelineRenderingCreateInfoWithGarbage.colorAttachmentCount    = static_cast<uint32_t>(garbageFormats.size());
3418         pipelineRenderingCreateInfoWithGarbage.pColorAttachmentFormats = garbageFormats.data();
3419         pipelineRenderingCreateInfo                                    = &pipelineRenderingCreateInfoWithGarbage;
3420     }
3421 #endif
3422 
3423     // If using dynamic state, create a single graphics pipeline and bind it
3424     if (m_data.useDynamicState)
3425     {
3426         pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
3427                                m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
3428         auto &pipeline = pipelines.back();
3429 
3430         pipeline.setDefaultColorBlendState().setDynamicState(dynamicState);
3431 
3432         if (useMesh)
3433         {
3434 #ifndef CTS_USES_VULKANSC
3435             pipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3436                                                           ShaderWrapper(), meshShader, rasterizationState, nullptr,
3437                                                           nullptr, shadingRateState, pipelineRenderingCreateInfo);
3438 #endif // CTS_USES_VULKANSC
3439         }
3440         else
3441         {
3442             pipeline.setupVertexInputState(vertexInputState)
3443                 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3444                                                   //1u,
3445                                                   vertShader, rasterizationState, ShaderWrapper(), ShaderWrapper(),
3446                                                   geomShader, DE_NULL, shadingRateState, pipelineRenderingCreateInfo);
3447         }
3448 
3449         pipeline
3450             .setupFragmentShaderState(pipelineLayout, renderPass, 0u,
3451                                       //1u,
3452                                       fragShader, depthStencilState, multisampleState)
3453             .setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
3454             //.setupFragmentOutputState(renderPass, 1u, DE_NULL, multisampleState)
3455             .setMonolithicPipelineLayout(pipelineLayout)
3456             .buildPipeline();
3457 
3458         vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3459     }
3460 
3461     // Push constant block (must match shaders).
3462     struct
3463     {
3464         int32_t shadingRate;
3465         uint32_t instanceIndex;
3466     } pushConstantBlock;
3467 
3468     for (int32_t i = 0; i < NUM_TRIANGLES; ++i)
3469     {
3470         if (!useMesh)
3471         {
3472             // Bind vertex attributes pointing to the next triangle
3473             VkDeviceSize vertexBufferOffset = i * 3 * 2 * sizeof(float);
3474             vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
3475         }
3476 
3477         // Put primitive shading rate and instance index (used in mesh shading cases) in push constants.
3478         pushConstantBlock.shadingRate   = PrimIDToPrimitiveShadingRate(i);
3479         pushConstantBlock.instanceIndex = static_cast<uint32_t>(i);
3480         vk.cmdPushConstants(cmdBuffer, *pipelineLayout, allShaderStages, 0, pushConstantSize, &pushConstantBlock);
3481 
3482         if (m_data.useDynamicState)
3483         {
3484             VkExtent2D fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
3485             vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, m_data.combinerOp);
3486         }
3487         else
3488         {
3489             // Create a new pipeline with the desired pipeline shading rate
3490             shadingRateState->fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
3491 
3492             pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
3493                                    m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
3494             auto &pipeline = pipelines.back();
3495 
3496             pipeline.setDefaultColorBlendState().setDynamicState(dynamicState);
3497 
3498             if (useMesh)
3499             {
3500 #ifndef CTS_USES_VULKANSC
3501                 pipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3502                                                               ShaderWrapper(), meshShader, rasterizationState, nullptr,
3503                                                               nullptr, shadingRateState, dynamicRenderingState);
3504 #endif // CTS_USES_VULKANSC
3505             }
3506             else
3507             {
3508                 pipeline.setupVertexInputState(vertexInputState)
3509                     .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShader,
3510                                                       rasterizationState, ShaderWrapper(), ShaderWrapper(), geomShader,
3511                                                       DE_NULL, shadingRateState, dynamicRenderingState);
3512             }
3513 
3514             pipeline
3515                 .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShader, depthStencilState,
3516                                           multisampleState)
3517 #ifndef CTS_USES_VULKANSC
3518                 .setRenderingColorAttachmentsInfo(dynamicRenderingState)
3519 #endif
3520                 .setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
3521                 .setMonolithicPipelineLayout(pipelineLayout)
3522                 .buildPipeline();
3523 
3524             vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3525         }
3526 
3527         if (useMesh)
3528         {
3529 #ifndef CTS_USES_VULKANSC
3530             // Create a single workgroup to draw one triangle. The "primitive id" will be in the push constants.
3531             vk.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
3532 #endif // CTS_USES_VULKANSC
3533         }
3534         else
3535         {
3536             // Draw one triangle, with "primitive ID" in gl_InstanceIndex
3537             vk.cmdDraw(cmdBuffer, 3u, 1, 0u, i);
3538         }
3539     }
3540 }
3541 
3542 } // namespace
3543 
createBasicTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,SharedGroupParams groupParams)3544 void createBasicTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *parentGroup, SharedGroupParams groupParams)
3545 {
3546     typedef struct
3547     {
3548         uint32_t count;
3549         const char *name;
3550     } TestGroupCase;
3551 
3552     typedef struct
3553     {
3554         VkExtent2D count;
3555         const char *name;
3556     } TestGroupCase2D;
3557 
3558     typedef struct
3559     {
3560         AttachmentUsage usage;
3561         const char *name;
3562     } TestGroupUsageCase;
3563 
3564     TestGroupCase groupCases[] = {
3565         // basic tests
3566         {0, "basic"},
3567         // use pSampleMask
3568         {1, "apisamplemask"},
3569         // use gl_SampleMaskIn
3570         {2, "samplemaskin"},
3571         // conservative underestimation
3572         {3, "conservativeunder"},
3573         // conservative overestimation
3574         {4, "conservativeover"},
3575         // depth shader output
3576         {5, "fragdepth"},
3577         // stencil shader output
3578         {6, "fragstencil"},
3579         // multiple viewports and gl_ViewportIndex
3580         {7, "multiviewport"},
3581         // multiple layer color, single layer shading rate
3582         {8, "colorlayered"},
3583         // multiple layer color, multiple layers shading rate
3584         {9, "srlayered"},
3585         // multiview
3586         {10, "multiview"},
3587         // multiview and multilayer shading rate
3588         {11, "multiviewsrlayered"},
3589         // multiview with correlation mask
3590         {12, "multiviewcorrelation"},
3591         // fragment shader interlock
3592         {13, "interlock"},
3593         // custom sample locations
3594         {14, "samplelocations"},
3595         // enable sample shading in createinfo
3596         {15, "sampleshadingenable"},
3597         // enable sample shading by using gl_SampleID
3598         {16, "sampleshadinginput"},
3599 #ifndef CTS_USES_VULKANSC
3600         // depth shader output
3601         {17, "fragdepth_early_late"},
3602         // stencil shader output
3603         {18, "fragstencil_early_late"},
3604 #endif
3605         {19, "fragdepth_clear"},
3606         {20, "fragstencil_clear"},
3607         {21, "fragdepth_baselevel"},
3608         {22, "fragstencil_baselevel"},
3609         {23, "multipass"},
3610         {24, "multipass_fragdepth"},
3611         {25, "multipass_fragstencil"},
3612 #ifndef CTS_USES_VULKANSC
3613         {26, "maintenance6"},
3614 #endif
3615     };
3616 
3617     TestGroupCase dynCases[] = {
3618         // uses dynamic shading rate state
3619         {1, "dynamic"},
3620         // uses static shading rate state
3621         {0, "static"},
3622     };
3623 
3624     TestGroupUsageCase attCases[] = {
3625         // no shading rate attachment
3626         {AttachmentUsage::NO_ATTACHMENT, "noattachment"},
3627         // has shading rate attachment
3628         {AttachmentUsage::WITH_ATTACHMENT, "attachment"},
3629         // no shading rate attachment pointer
3630         {AttachmentUsage::NO_ATTACHMENT_PTR, "noattachmentptr"},
3631         // has shading rate attachment without imageview
3632         {AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW, "attachment_noimageview"},
3633     };
3634 
3635     TestGroupCase shdCases[] = {
3636         // shader doesn't write rate
3637         {0, "noshaderrate"},
3638         // shader writes rate
3639         {1, "shaderrate"},
3640     };
3641 
3642     TestGroupCase combCases[] = {
3643         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, "keep"},
3644         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR, "replace"},
3645         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR, "min"},
3646         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR, "max"},
3647         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR, "mul"},
3648     };
3649 
3650     TestGroupCase2D extentCases[] = {
3651         {{1, 1}, "1x1"}, {{4, 4}, "4x4"}, {{33, 35}, "33x35"}, {{151, 431}, "151x431"}, {{256, 256}, "256x256"},
3652     };
3653 
3654     TestGroupCase sampCases[] = {
3655         {VK_SAMPLE_COUNT_1_BIT, "samples1"}, {VK_SAMPLE_COUNT_2_BIT, "samples2"},   {VK_SAMPLE_COUNT_4_BIT, "samples4"},
3656         {VK_SAMPLE_COUNT_8_BIT, "samples8"}, {VK_SAMPLE_COUNT_16_BIT, "samples16"},
3657     };
3658 
3659     TestGroupCase shaderCases[] = {
3660         // vertex shader only
3661         {0, "vs"},
3662         // vertex and geometry shader
3663         {1, "gs"},
3664 #ifndef CTS_USES_VULKANSC
3665         // mesh shader
3666         {2, "ms"},
3667 #endif // CTS_USES_VULKANSC
3668     };
3669 
3670     int32_t seed = 0;
3671 
3672     for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groupCases); groupNdx++)
3673     {
3674         if (groupParams->useDynamicRendering && (groupNdx == 12 || groupNdx == 26))
3675             continue;
3676 
3677         if (groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3678         {
3679             // for graphics pipeline library we need to repeat only selected groups
3680             if (std::set<int>{2, 3, 4, 10, 11, 12, 13, 14, 15}.count(groupNdx) == 0)
3681                 continue;
3682         }
3683 
3684         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, groupCases[groupNdx].name));
3685         for (int dynNdx = 0; dynNdx < DE_LENGTH_OF_ARRAY(dynCases); dynNdx++)
3686         {
3687             // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3688             if (groupParams->useSecondaryCmdBuffer && (dynNdx != 0))
3689                 continue;
3690 
3691             de::MovePtr<tcu::TestCaseGroup> dynGroup(new tcu::TestCaseGroup(testCtx, dynCases[dynNdx].name));
3692             for (int attNdx = 0; attNdx < DE_LENGTH_OF_ARRAY(attCases); attNdx++)
3693             {
3694                 if (groupParams->useDynamicRendering && attCases[attNdx].usage == AttachmentUsage::NO_ATTACHMENT_PTR)
3695                     continue;
3696 
3697                 // WITH_ATTACHMENT_WITHOUT_IMAGEVIEW is only for VkRenderingFragmentShadingRateAttachmentInfoKHR.
3698                 if (!groupParams->useDynamicRendering &&
3699                     attCases[attNdx].usage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW)
3700                     continue;
3701 
3702                 de::MovePtr<tcu::TestCaseGroup> attGroup(new tcu::TestCaseGroup(testCtx, attCases[attNdx].name));
3703                 for (int shdNdx = 0; shdNdx < DE_LENGTH_OF_ARRAY(shdCases); shdNdx++)
3704                 {
3705                     de::MovePtr<tcu::TestCaseGroup> shdGroup(new tcu::TestCaseGroup(testCtx, shdCases[shdNdx].name));
3706                     for (int cmb0Ndx = 0; cmb0Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb0Ndx++)
3707                     {
3708                         de::MovePtr<tcu::TestCaseGroup> cmb0Group(
3709                             new tcu::TestCaseGroup(testCtx, combCases[cmb0Ndx].name));
3710                         for (int cmb1Ndx = 0; cmb1Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb1Ndx++)
3711                         {
3712                             de::MovePtr<tcu::TestCaseGroup> cmb1Group(
3713                                 new tcu::TestCaseGroup(testCtx, combCases[cmb1Ndx].name));
3714                             for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
3715                             {
3716                                 // reduce number of cases repeat every other extent case for graphics pipeline library
3717                                 if ((groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) &&
3718                                     ((extNdx % 2) == 1))
3719                                     continue;
3720 
3721                                 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3722                                 if (groupParams->useSecondaryCmdBuffer && (extNdx != 1))
3723                                     continue;
3724 
3725                                 de::MovePtr<tcu::TestCaseGroup> extGroup(
3726                                     new tcu::TestCaseGroup(testCtx, extentCases[extNdx].name));
3727                                 for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
3728                                 {
3729                                     // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3730                                     if (groupParams->useSecondaryCmdBuffer && (sampNdx != 1))
3731                                         continue;
3732 
3733                                     de::MovePtr<tcu::TestCaseGroup> sampGroup(
3734                                         new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name));
3735                                     for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderCases); shaderNdx++)
3736                                     {
3737                                         de::MovePtr<tcu::TestCaseGroup> shaderGroup(
3738                                             new tcu::TestCaseGroup(testCtx, shaderCases[shaderNdx].name));
3739                                         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3740                                         if (groupParams->useSecondaryCmdBuffer && (shaderNdx != 0))
3741                                             continue;
3742 
3743                                         bool useApiSampleMask = groupNdx == 1;
3744                                         bool useSampleMaskIn  = groupNdx == 2;
3745                                         bool consRast         = groupNdx == 3 || groupNdx == 4;
3746                                         bool fragDepth        = groupNdx == 5 || groupNdx == 17 || groupNdx == 19 ||
3747                                                          groupNdx == 21 || groupNdx == 24;
3748                                         bool fragStencil = groupNdx == 6 || groupNdx == 18 || groupNdx == 20 ||
3749                                                            groupNdx == 22 || groupNdx == 25;
3750                                         bool multiViewport       = groupNdx == 7;
3751                                         bool colorLayered        = groupNdx == 8 || groupNdx == 9;
3752                                         bool srLayered           = groupNdx == 9 || groupNdx == 11;
3753                                         bool multiView           = groupNdx == 10 || groupNdx == 11 || groupNdx == 12;
3754                                         bool correlationMask     = groupNdx == 12;
3755                                         bool interlock           = groupNdx == 13;
3756                                         bool sampleLocations     = groupNdx == 14;
3757                                         bool sampleShadingEnable = groupNdx == 15;
3758                                         bool sampleShadingInput  = groupNdx == 16;
3759                                         bool useGeometryShader   = (shaderCases[shaderNdx].count == 1u);
3760                                         bool useMeshShader       = (shaderCases[shaderNdx].count == 2u);
3761                                         bool earlyAndLateTest    = groupNdx == 17 || groupNdx == 18;
3762                                         bool opClear             = groupNdx == 19 || groupNdx == 20;
3763                                         uint32_t baseMipLevel    = (groupNdx == 21 || groupNdx == 22) ? 1 : 0;
3764                                         bool multiPass           = (groupNdx == 23 || groupNdx == 24 || groupNdx == 25);
3765                                         bool maintenance6        = (groupNdx == 26);
3766 
3767                                         VkConservativeRasterizationModeEXT conservativeMode =
3768                                             (groupNdx == 3) ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT :
3769                                                               VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3770                                         uint32_t numColorLayers = (colorLayered || multiView) ? 2u : 1u;
3771 
3772                                         // Don't bother with geometry shader if we're not testing shader writes
3773                                         if (useGeometryShader && !shdCases[shdNdx].count)
3774                                             continue;
3775 
3776                                         // reduce number of tests
3777                                         if ((groupNdx != 0) &&
3778                                             (!dynCases[dynNdx].count ||
3779                                              !(combCases[cmb0Ndx].count ==
3780                                                    VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR ||
3781                                                combCases[cmb0Ndx].count ==
3782                                                    VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
3783                                              !(combCases[cmb1Ndx].count ==
3784                                                    VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR ||
3785                                                combCases[cmb1Ndx].count ==
3786                                                    VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
3787                                             continue;
3788 
3789                                         // Don't bother with geometry shader if we're testing conservative raster, sample mask, depth/stencil
3790                                         if (useGeometryShader && (useApiSampleMask || useSampleMaskIn || consRast ||
3791                                                                   fragDepth || fragStencil || maintenance6))
3792                                             continue;
3793 
3794                                         // Don't bother with geometry shader if we're testing non-dynamic state
3795                                         if (useGeometryShader && !dynCases[dynNdx].count)
3796                                             continue;
3797 
3798                                         // Only test multiViewport/layered with shaderWritesRate
3799                                         if ((multiViewport || colorLayered) && !shdCases[shdNdx].count)
3800                                             continue;
3801 
3802                                         // Can't test layered shading rate attachment without an attachment
3803                                         if (srLayered && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3804                                             continue;
3805 
3806                                         // Test opClear for DS cases with only attachment and renderpass.
3807                                         if (opClear && (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3808                                                         groupParams->useDynamicRendering))
3809                                             continue;
3810 
3811                                         // Test baseLevel for DS cases with only attachment, single sample, and renderpass.
3812                                         if (baseMipLevel > 0 &&
3813                                             (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3814                                              groupParams->useDynamicRendering ||
3815                                              sampCases[sampNdx].count > VK_SAMPLE_COUNT_1_BIT))
3816                                             continue;
3817 
3818                                         // Test multipass for DS cases with only attachment, single sample, and renderpass.
3819                                         if (multiPass && (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3820                                                           groupParams->useDynamicRendering ||
3821                                                           sampCases[sampNdx].count > VK_SAMPLE_COUNT_1_BIT))
3822                                             continue;
3823 
3824                                         // Skip maintenance6 tests if there is no FSR attachment
3825                                         if (maintenance6 && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3826                                             continue;
3827 
3828                                         CaseDef c{
3829                                             groupParams,               // SharedGroupParams groupParams;
3830                                             seed++,                    // int32_t seed;
3831                                             extentCases[extNdx].count, // VkExtent2D framebufferDim;
3832                                             (VkSampleCountFlagBits)sampCases[sampNdx]
3833                                                 .count, // VkSampleCountFlagBits samples;
3834                                             {(VkFragmentShadingRateCombinerOpKHR)combCases[cmb0Ndx].count,
3835                                              (VkFragmentShadingRateCombinerOpKHR)combCases[cmb1Ndx]
3836                                                  .count},           // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3837                                             attCases[attNdx].usage, // AttachmentUsage attachmentUsage;
3838                                             (bool)shdCases[shdNdx].count, // bool shaderWritesRate;
3839                                             useGeometryShader,            // bool geometryShader;
3840                                             useMeshShader,                // bool meshShader;
3841                                             (bool)dynCases[dynNdx].count, // bool useDynamicState;
3842                                             useApiSampleMask,             // bool useApiSampleMask;
3843                                             useSampleMaskIn,              // bool useSampleMaskIn;
3844                                             consRast,                     // bool conservativeEnable;
3845                                             conservativeMode, // VkConservativeRasterizationModeEXT conservativeMode;
3846                                             fragDepth || fragStencil, // bool useDepthStencil;
3847                                             fragDepth,                // bool fragDepth;
3848                                             fragStencil,              // bool fragStencil;
3849                                             multiViewport,            // bool multiViewport;
3850                                             colorLayered,             // bool colorLayered;
3851                                             srLayered,                // bool srLayered;
3852                                             numColorLayers,           // uint32_t numColorLayers;
3853                                             multiView,                // bool multiView;
3854                                             correlationMask,          // bool correlationMask;
3855                                             interlock,                // bool interlock;
3856                                             sampleLocations,          // bool sampleLocations;
3857                                             sampleShadingEnable,      // bool sampleShadingEnable;
3858                                             sampleShadingInput,       // bool sampleShadingInput;
3859                                             false,                    // bool sampleMaskTest;
3860                                             earlyAndLateTest,         // bool earlyAndLateTest;
3861                                             false,                    // bool garbageAttachment;
3862                                             opClear,                  // bool dsClearOp;
3863                                             baseMipLevel,             // uint32_t dsBaseMipLevel;
3864                                             multiPass,                // bool multiSubpasses;
3865                                             maintenance6,             // bool maintenance6;
3866                                         };
3867 
3868                                         sampGroup->addChild(new FSRTestCase(testCtx, shaderCases[shaderNdx].name, c));
3869                                     }
3870                                     extGroup->addChild(sampGroup.release());
3871                                 }
3872                                 cmb1Group->addChild(extGroup.release());
3873                             }
3874                             cmb0Group->addChild(cmb1Group.release());
3875                         }
3876                         shdGroup->addChild(cmb0Group.release());
3877                     }
3878                     attGroup->addChild(shdGroup.release());
3879                 }
3880                 dynGroup->addChild(attGroup.release());
3881             }
3882             group->addChild(dynGroup.release());
3883         }
3884         parentGroup->addChild(group.release());
3885     }
3886 
3887     {
3888         // Single tests that don't need to be part of above test matrix
3889         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc_tests"));
3890 
3891         if (!groupParams->useSecondaryCmdBuffer)
3892         {
3893             group->addChild(new FSRTestCase(
3894                 testCtx, "sample_mask_test",
3895                 {
3896                     groupParams,           // SharedGroupParams groupParams;
3897                     123,                   // int32_t seed;
3898                     {32, 33},              // VkExtent2D framebufferDim;
3899                     VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
3900                     {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3901                      VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3902                     AttachmentUsage::NO_ATTACHMENT,                  // AttachmentUsage attachmentUsage;
3903                     true,                                            // bool shaderWritesRate;
3904                     false,                                           // bool geometryShader;
3905                     false,                                           // bool meshShader;
3906                     false,                                           // bool useDynamicState;
3907                     true,                                            // bool useApiSampleMask;
3908                     false,                                           // bool useSampleMaskIn;
3909                     false,                                           // bool conservativeEnable;
3910                     VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, // VkConservativeRasterizationModeEXT conservativeMode;
3911                     false,                                                // bool useDepthStencil;
3912                     false,                                                // bool fragDepth;
3913                     false,                                                // bool fragStencil;
3914                     false,                                                // bool multiViewport;
3915                     false,                                                // bool colorLayered;
3916                     false,                                                // bool srLayered;
3917                     1u,                                                   // uint32_t numColorLayers;
3918                     false,                                                // bool multiView;
3919                     false,                                                // bool correlationMask;
3920                     false,                                                // bool interlock;
3921                     false,                                                // bool sampleLocations;
3922                     false,                                                // bool sampleShadingEnable;
3923                     false,                                                // bool sampleShadingInput;
3924                     true,                                                 // bool sampleMaskTest;
3925                     false,                                                // bool earlyAndLateTest;
3926                     false,                                                // bool garbageAttachment;
3927                     false,                                                // bool dsClearOp;
3928                     0,                                                    // uint32_t dsBaseMipLevel;
3929                     false,                                                // bool multiSubpasses;
3930                     false,                                                // bool maintenance6;
3931                 }));
3932         }
3933 
3934 #ifndef CTS_USES_VULKANSC
3935         if (groupParams->useDynamicRendering &&
3936             groupParams->pipelineConstructionType != vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3937         {
3938             group->addChild(new FSRTestCase(
3939                 testCtx, "garbage_color_attachment",
3940                 {
3941                     groupParams,           // SharedGroupParams groupParams;
3942                     123,                   // int32_t seed;
3943                     {32, 33},              // VkExtent2D framebufferDim;
3944                     VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
3945                     {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3946                      VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3947                     AttachmentUsage::NO_ATTACHMENT,                  // AttachmentUsage attachmentUsage;
3948                     false,                                           // bool shaderWritesRate;
3949                     false,                                           // bool geometryShader;
3950                     false,                                           // bool meshShader;
3951                     false,                                           // bool useDynamicState;
3952                     false,                                           // bool useApiSampleMask;
3953                     false,                                           // bool useSampleMaskIn;
3954                     false,                                           // bool conservativeEnable;
3955                     VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, // VkConservativeRasterizationModeEXT conservativeMode;
3956                     false,                                                // bool useDepthStencil;
3957                     false,                                                // bool fragDepth;
3958                     false,                                                // bool fragStencil;
3959                     false,                                                // bool multiViewport;
3960                     false,                                                // bool colorLayered;
3961                     false,                                                // bool srLayered;
3962                     1u,                                                   // uint32_t numColorLayers;
3963                     false,                                                // bool multiView;
3964                     false,                                                // bool correlationMask;
3965                     false,                                                // bool interlock;
3966                     false,                                                // bool sampleLocations;
3967                     false,                                                // bool sampleShadingEnable;
3968                     false,                                                // bool sampleShadingInput;
3969                     false,                                                // bool sampleMaskTest;
3970                     false,                                                // bool earlyAndLateTest;
3971                     true,                                                 // bool garbageAttachment;
3972                     false,                                                // bool dsClearOp;
3973                     0,                                                    // uint32_t dsBaseMipLevel;
3974                     false,                                                // bool multiSubpasses;
3975                     false,                                                // bool maintenance6;
3976                 }));
3977         }
3978 #endif // CTS_USES_VULKANSC
3979 
3980         parentGroup->addChild(group.release());
3981     }
3982 }
3983 
3984 } // namespace FragmentShadingRate
3985 } // namespace vkt
3986