xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  * Copyright (c) 2017 Google Inc.
8  * Copyright (c) 2023 LunarG, Inc.
9  * Copyright (c) 2023 Nintendo
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  *//*!
24  * \file
25  * \brief Multisample Tests
26  *//*--------------------------------------------------------------------*/
27 
28 #include "vktPipelineMultisampleTests.hpp"
29 #include "vktPipelineMultisampleImageTests.hpp"
30 #include "vktPipelineMultisampleSampleLocationsExtTests.hpp"
31 #include "vktPipelineMultisampleMixedAttachmentSamplesTests.hpp"
32 #include "vktPipelineMultisampleResolveRenderAreaTests.hpp"
33 #include "vktPipelineMultisampleShaderFragmentMaskTests.hpp"
34 #include "vktPipelineMultisampledRenderToSingleSampledTests.hpp"
35 #include "vktPipelineClearUtil.hpp"
36 #include "vktPipelineImageUtil.hpp"
37 #include "vktPipelineVertexUtil.hpp"
38 #include "vktPipelineReferenceRenderer.hpp"
39 #include "vktTestCase.hpp"
40 #include "vktTestCaseUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkMemUtil.hpp"
43 #include "vkPrograms.hpp"
44 #include "vkQueryUtil.hpp"
45 #include "vkRef.hpp"
46 #include "vkRefUtil.hpp"
47 #include "vkCmdUtil.hpp"
48 #include "vkTypeUtil.hpp"
49 #include "vkObjUtil.hpp"
50 #include "vkBufferWithMemory.hpp"
51 #include "vkImageWithMemory.hpp"
52 #include "vkBuilderUtil.hpp"
53 #include "vkBarrierUtil.hpp"
54 #include "tcuImageCompare.hpp"
55 #include "tcuTestLog.hpp"
56 #include "deUniquePtr.hpp"
57 #include "deSharedPtr.hpp"
58 #include "deStringUtil.hpp"
59 #include "deMemory.h"
60 
61 #include <sstream>
62 #include <vector>
63 #include <map>
64 #include <memory>
65 #include <algorithm>
66 #include <set>
67 #include <array>
68 #include <utility>
69 
70 namespace vkt
71 {
72 namespace pipeline
73 {
74 
75 using namespace vk;
76 
77 namespace
78 {
79 enum GeometryType
80 {
81     GEOMETRY_TYPE_OPAQUE_TRIANGLE,
82     GEOMETRY_TYPE_OPAQUE_LINE,
83     GEOMETRY_TYPE_OPAQUE_POINT,
84     GEOMETRY_TYPE_OPAQUE_QUAD,
85     GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH, //!< placed at z = 0.5
86     GEOMETRY_TYPE_TRANSLUCENT_QUAD,
87     GEOMETRY_TYPE_INVISIBLE_TRIANGLE,
88     GEOMETRY_TYPE_INVISIBLE_QUAD,
89     GEOMETRY_TYPE_GRADIENT_QUAD
90 };
91 
92 enum TestModeBits
93 {
94     TEST_MODE_DEPTH_BIT   = 1u,
95     TEST_MODE_STENCIL_BIT = 2u,
96 };
97 typedef uint32_t TestModeFlags;
98 
99 enum RenderType
100 {
101     // resolve multisample rendering to single sampled image
102     RENDER_TYPE_RESOLVE = 0u,
103 
104     // copy samples to an array of single sampled images
105     RENDER_TYPE_COPY_SAMPLES = 1u,
106 
107     // render first with only depth/stencil and then with color + depth/stencil
108     RENDER_TYPE_DEPTHSTENCIL_ONLY = 2u,
109 
110     // render using color attachment at location 1 and location 0 set as unused
111     RENDER_TYPE_UNUSED_ATTACHMENT = 3u,
112 
113     // render using color attachment with single sample, required by alpha_to_one tests.
114     RENDER_TYPE_SINGLE_SAMPLE = 4u
115 };
116 
117 enum ImageBackingMode
118 {
119     IMAGE_BACKING_MODE_REGULAR = 0u,
120     IMAGE_BACKING_MODE_SPARSE
121 };
122 
123 struct MultisampleTestParams
124 {
125     PipelineConstructionType pipelineConstructionType;
126     GeometryType geometryType;
127     float pointSize;
128     ImageBackingMode backingMode;
129     bool useFragmentShadingRate;
130 };
131 
132 void initMultisamplePrograms(SourceCollections &sources, MultisampleTestParams params);
133 bool isSupportedSampleCount(const InstanceInterface &instanceInterface, VkPhysicalDevice physicalDevice,
134                             VkSampleCountFlagBits rasterizationSamples);
135 bool isSupportedDepthStencilFormat(const InstanceInterface &vki, const VkPhysicalDevice physDevice,
136                                    const VkFormat format);
137 VkPipelineColorBlendAttachmentState getDefaultColorBlendAttachmentState(void);
138 VkPipelineColorBlendAttachmentState getAlphaToCoverageBlendState(bool blendEnable);
139 uint32_t getUniqueColorsCount(const tcu::ConstPixelBufferAccess &image);
140 VkImageAspectFlags getImageAspectFlags(const VkFormat format);
141 VkPrimitiveTopology getPrimitiveTopology(const GeometryType geometryType);
142 std::vector<Vertex4RGBA> generateVertices(const GeometryType geometryType);
143 VkFormat findSupportedDepthStencilFormat(Context &context, const bool useDepth, const bool useStencil);
144 
145 class MultisampleTest : public vkt::TestCase
146 {
147 public:
148     MultisampleTest(tcu::TestContext &testContext, const std::string &name,
149                     PipelineConstructionType pipelineConstructionType,
150                     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
151                     const VkPipelineColorBlendAttachmentState &blendState, GeometryType geometryType, float pointSize,
152                     ImageBackingMode backingMode, const bool useFragmentShadingRate);
~MultisampleTest(void)153     virtual ~MultisampleTest(void)
154     {
155     }
156 
157     virtual void initPrograms(SourceCollections &programCollection) const;
158     virtual TestInstance *createInstance(Context &context) const;
159     virtual void checkSupport(Context &context) const;
160 
161 protected:
162     virtual TestInstance *createMultisampleTestInstance(
163         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
164         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
165         const VkPipelineColorBlendAttachmentState &colorBlendState) const = 0;
166 
167     const PipelineConstructionType m_pipelineConstructionType;
168     VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
169     const VkPipelineColorBlendAttachmentState m_colorBlendState;
170     const GeometryType m_geometryType;
171     const float m_pointSize;
172     const ImageBackingMode m_backingMode;
173     std::vector<VkSampleMask> m_sampleMask;
174     bool m_useFragmentShadingRate;
175 };
176 
177 class RasterizationSamplesTest : public MultisampleTest
178 {
179 public:
180     RasterizationSamplesTest(tcu::TestContext &testContext, const std::string &name,
181                              PipelineConstructionType pipelineConstructionType,
182                              VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType, float pointSize,
183                              ImageBackingMode backingMode, TestModeFlags modeFlags, const bool useFragmentShadingRate);
~RasterizationSamplesTest(void)184     virtual ~RasterizationSamplesTest(void)
185     {
186     }
187 
188 protected:
189     virtual TestInstance *createMultisampleTestInstance(
190         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
191         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
192         const VkPipelineColorBlendAttachmentState &colorBlendState) const;
193 
194     static VkPipelineMultisampleStateCreateInfo getRasterizationSamplesStateParams(
195         VkSampleCountFlagBits rasterizationSamples);
196 
197     const ImageBackingMode m_backingMode;
198     const TestModeFlags m_modeFlags;
199 };
200 
201 class MinSampleShadingTest : public MultisampleTest
202 {
203 public:
204     MinSampleShadingTest(tcu::TestContext &testContext, const std::string &name,
205                          const PipelineConstructionType pipelineConstructionType,
206                          VkSampleCountFlagBits rasterizationSamples, float minSampleShading, GeometryType geometryType,
207                          float pointSize, ImageBackingMode backingMode, const bool minSampleShadingEnabled,
208                          const bool useFragmentShadingRate);
~MinSampleShadingTest(void)209     virtual ~MinSampleShadingTest(void)
210     {
211     }
212 
213 protected:
214     virtual void initPrograms(SourceCollections &programCollection) const;
215     virtual void checkSupport(Context &context) const;
216     virtual TestInstance *createMultisampleTestInstance(
217         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
218         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
219         const VkPipelineColorBlendAttachmentState &colorBlendState) const;
220 
221     static VkPipelineMultisampleStateCreateInfo getMinSampleShadingStateParams(
222         VkSampleCountFlagBits rasterizationSamples, float minSampleShading, bool minSampleShadingEnabled);
223 
224     const float m_pointSize;
225     const ImageBackingMode m_backingMode;
226     const bool m_minSampleShadingEnabled;
227 };
228 
229 class SampleMaskTest : public MultisampleTest
230 {
231 public:
232     SampleMaskTest(tcu::TestContext &testContext, const std::string &name,
233                    const PipelineConstructionType pipelineConstructionType, VkSampleCountFlagBits rasterizationSamples,
234                    const std::vector<VkSampleMask> &sampleMask, GeometryType geometryType, float pointSize,
235                    ImageBackingMode backingMode, const bool useFragmentShadingRate);
236 
~SampleMaskTest(void)237     virtual ~SampleMaskTest(void)
238     {
239     }
240 
241 protected:
242     virtual TestInstance *createMultisampleTestInstance(
243         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
244         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
245         const VkPipelineColorBlendAttachmentState &colorBlendState) const;
246 
247     static VkPipelineMultisampleStateCreateInfo getSampleMaskStateParams(VkSampleCountFlagBits rasterizationSamples,
248                                                                          const std::vector<VkSampleMask> &sampleMask);
249 
250     const ImageBackingMode m_backingMode;
251 };
252 
253 class AlphaToOneTest : public MultisampleTest
254 {
255 public:
256     AlphaToOneTest(tcu::TestContext &testContext, const std::string &name,
257                    const PipelineConstructionType pipelineConstructionType, VkSampleCountFlagBits rasterizationSamples,
258                    ImageBackingMode backingMode, const bool useFragmentShadingRate);
259 
~AlphaToOneTest(void)260     virtual ~AlphaToOneTest(void)
261     {
262     }
263 
264 protected:
265     virtual void checkSupport(Context &context) const;
266     virtual TestInstance *createMultisampleTestInstance(
267         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
268         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
269         const VkPipelineColorBlendAttachmentState &colorBlendState) const;
270 
271     static VkPipelineMultisampleStateCreateInfo getAlphaToOneStateParams(VkSampleCountFlagBits rasterizationSamples);
272     static VkPipelineColorBlendAttachmentState getAlphaToOneBlendState(void);
273 
274     const ImageBackingMode m_backingMode;
275 };
276 
277 class AlphaToCoverageTest : public MultisampleTest
278 {
279 public:
280     AlphaToCoverageTest(tcu::TestContext &testContext, const std::string &name,
281                         const PipelineConstructionType pipelineConstructionType,
282                         VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType,
283                         ImageBackingMode backingMode, const bool useFragmentShadingRate, const bool checkDepthBuffer);
284 
~AlphaToCoverageTest(void)285     virtual ~AlphaToCoverageTest(void)
286     {
287     }
288     void initPrograms(SourceCollections &programCollection) const override;
289 
290 protected:
291     TestInstance *createMultisampleTestInstance(
292         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
293         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
294         const VkPipelineColorBlendAttachmentState &colorBlendState) const override;
295 
296     static VkPipelineMultisampleStateCreateInfo getAlphaToCoverageStateParams(
297         VkSampleCountFlagBits rasterizationSamples);
298 
299     GeometryType m_geometryType;
300     const ImageBackingMode m_backingMode;
301     const bool m_checkDepthBuffer;
302 };
303 
304 class AlphaToCoverageNoColorAttachmentTest : public MultisampleTest
305 {
306 public:
307     AlphaToCoverageNoColorAttachmentTest(tcu::TestContext &testContext, const std::string &name,
308                                          const PipelineConstructionType pipelineConstructionType,
309                                          VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType,
310                                          ImageBackingMode backingMode, const bool useFragmentShadingRate);
311 
~AlphaToCoverageNoColorAttachmentTest(void)312     virtual ~AlphaToCoverageNoColorAttachmentTest(void)
313     {
314     }
315 
316 protected:
317     virtual TestInstance *createMultisampleTestInstance(
318         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
319         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
320         const VkPipelineColorBlendAttachmentState &colorBlendState) const;
321 
322     static VkPipelineMultisampleStateCreateInfo getStateParams(VkSampleCountFlagBits rasterizationSamples);
323 
324     GeometryType m_geometryType;
325     const ImageBackingMode m_backingMode;
326 };
327 
328 class AlphaToCoverageColorUnusedAttachmentTest : public MultisampleTest
329 {
330 public:
331     AlphaToCoverageColorUnusedAttachmentTest(tcu::TestContext &testContext, const std::string &name,
332                                              const PipelineConstructionType pipelineConstructionType,
333                                              VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType,
334                                              ImageBackingMode backingMode, const bool useFragmentShadingRate);
335 
~AlphaToCoverageColorUnusedAttachmentTest(void)336     virtual ~AlphaToCoverageColorUnusedAttachmentTest(void)
337     {
338     }
339 
340 protected:
341     virtual void initPrograms(SourceCollections &programCollection) const;
342 
343     virtual TestInstance *createMultisampleTestInstance(
344         Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
345         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
346         const VkPipelineColorBlendAttachmentState &colorBlendState) const;
347 
348     static VkPipelineMultisampleStateCreateInfo getStateParams(VkSampleCountFlagBits rasterizationSamples);
349 
350     GeometryType m_geometryType;
351     const ImageBackingMode m_backingMode;
352 };
353 
354 class SampleMaskWithConservativeTest : public vkt::TestCase
355 {
356 public:
357     SampleMaskWithConservativeTest(tcu::TestContext &testContext, const std::string &name,
358                                    const PipelineConstructionType pipelineConstructionType,
359                                    const VkSampleCountFlagBits rasterizationSamples,
360                                    const VkConservativeRasterizationModeEXT conservativeRasterizationMode,
361                                    const bool enableMinSampleShading, const float minSampleShading,
362                                    const bool enableSampleMask, const VkSampleMask sampleMask,
363                                    const bool enablePostDepthCoverage, const bool useFragmentShadingRate);
364 
~SampleMaskWithConservativeTest(void)365     ~SampleMaskWithConservativeTest(void)
366     {
367     }
368 
369     void initPrograms(SourceCollections &programCollection) const;
370     TestInstance *createInstance(Context &context) const;
371     virtual void checkSupport(Context &context) const;
372 
373 private:
374     const PipelineConstructionType m_pipelineConstructionType;
375     const VkSampleCountFlagBits m_rasterizationSamples;
376     const bool m_enableMinSampleShading;
377     float m_minSampleShading;
378     const bool m_enableSampleMask;
379     const VkSampleMask m_sampleMask;
380     const VkConservativeRasterizationModeEXT m_conservativeRasterizationMode;
381     const bool m_enablePostDepthCoverage;
382     const RenderType m_renderType;
383     const bool m_useFragmentShadingRate;
384 };
385 #ifndef CTS_USES_VULKANSC
386 class SampleMaskWithDepthTestTest : public vkt::TestCase
387 {
388 public:
389     SampleMaskWithDepthTestTest(tcu::TestContext &testContext, const std::string &name,
390                                 const PipelineConstructionType pipelineConstructionType,
391                                 const VkSampleCountFlagBits rasterizationSamples, const bool enablePostDepthCoverage,
392                                 const bool useFragmentShadingRate);
393 
~SampleMaskWithDepthTestTest(void)394     ~SampleMaskWithDepthTestTest(void)
395     {
396     }
397 
398     void initPrograms(SourceCollections &programCollection) const;
399     TestInstance *createInstance(Context &context) const;
400     virtual void checkSupport(Context &context) const;
401 
402 private:
403     const PipelineConstructionType m_pipelineConstructionType;
404     const VkSampleCountFlagBits m_rasterizationSamples;
405     const bool m_enablePostDepthCoverage;
406     const bool m_useFragmentShadingRate;
407 };
408 #endif // CTS_USES_VULKANSC
409 class MultisampleRenderer
410 {
411 public:
412     MultisampleRenderer(Context &context, PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
413                         const tcu::IVec2 &renderSize, const VkPrimitiveTopology topology,
414                         const std::vector<Vertex4RGBA> &vertices,
415                         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
416                         const VkPipelineColorBlendAttachmentState &blendState, const RenderType renderType,
417                         const ImageBackingMode backingMode, const bool useFragmentShadingRate);
418 
419     MultisampleRenderer(Context &context, PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
420                         const VkFormat depthStencilFormat, const tcu::IVec2 &renderSize, const bool useDepth,
421                         const bool useStencil, const uint32_t numTopologies, const VkPrimitiveTopology *pTopology,
422                         const std::vector<Vertex4RGBA> *pVertices,
423                         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
424                         const VkPipelineColorBlendAttachmentState &blendState, const RenderType renderType,
425                         const ImageBackingMode backingMode, const bool useFragmentShadingRate,
426                         const float depthClearValue = 1.0f);
427 
428     MultisampleRenderer(Context &context, PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
429                         const VkFormat depthStencilFormat, const tcu::IVec2 &renderSize, const bool useDepth,
430                         const bool useStencil, const bool useConservative, const bool useFragmentShadingRate,
431                         const uint32_t numTopologies, const VkPrimitiveTopology *pTopology,
432                         const std::vector<Vertex4RGBA> *pVertices,
433                         const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
434                         const VkPipelineColorBlendAttachmentState &blendState,
435                         const VkPipelineRasterizationConservativeStateCreateInfoEXT &conservativeStateCreateInfo,
436                         const RenderType renderType, const ImageBackingMode backingMode,
437                         const float depthClearValue = 1.0f);
438 
439     virtual ~MultisampleRenderer(void);
440 
441     de::MovePtr<tcu::TextureLevel> render(void);
442     de::MovePtr<tcu::TextureLevel> getSingleSampledImage(uint32_t sampleId);
443     de::MovePtr<tcu::TextureLevel> renderReusingDepth();
444 
445 protected:
446     void initialize(Context &context, const uint32_t numTopologies, const VkPrimitiveTopology *pTopology,
447                     const std::vector<Vertex4RGBA> *pVertices);
448 
449     Context &m_context;
450     const PipelineConstructionType m_pipelineConstructionType;
451 
452     const Unique<VkSemaphore> m_bindSemaphore;
453 
454     const VkFormat m_colorFormat;
455     const VkFormat m_depthStencilFormat;
456     tcu::IVec2 m_renderSize;
457     const bool m_useDepth;
458     const bool m_useStencil;
459     const bool m_useConservative;
460 
461     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
462     const VkPipelineColorBlendAttachmentState m_colorBlendState;
463     const VkPipelineRasterizationConservativeStateCreateInfoEXT m_rasterizationConservativeStateCreateInfo;
464 
465     const RenderType m_renderType;
466 
467     Move<VkImage> m_colorImage;
468     de::MovePtr<Allocation> m_colorImageAlloc;
469     Move<VkImageView> m_colorAttachmentView;
470 
471     Move<VkImage> m_resolveImage;
472     de::MovePtr<Allocation> m_resolveImageAlloc;
473     Move<VkImageView> m_resolveAttachmentView;
474 
475     struct PerSampleImage
476     {
477         Move<VkImage> m_image;
478         de::MovePtr<Allocation> m_imageAlloc;
479         Move<VkImageView> m_attachmentView;
480     };
481     std::vector<de::SharedPtr<PerSampleImage>> m_perSampleImages;
482 
483     Move<VkImage> m_depthStencilImage;
484     de::MovePtr<Allocation> m_depthStencilImageAlloc;
485     Move<VkImageView> m_depthStencilAttachmentView;
486 
487     RenderPassWrapper m_renderPass;
488 
489     ShaderWrapper m_vertexShaderModule;
490     ShaderWrapper m_fragmentShaderModule;
491 
492     ShaderWrapper m_copySampleVertexShaderModule;
493     ShaderWrapper m_copySampleFragmentShaderModule;
494 
495     Move<VkBuffer> m_vertexBuffer;
496     de::MovePtr<Allocation> m_vertexBufferAlloc;
497 
498     PipelineLayoutWrapper m_pipelineLayout;
499     std::vector<GraphicsPipelineWrapper> m_graphicsPipelines;
500 
501     Move<VkDescriptorSetLayout> m_copySampleDesciptorLayout;
502     Move<VkDescriptorPool> m_copySampleDesciptorPool;
503     Move<VkDescriptorSet> m_copySampleDesciptorSet;
504 
505     PipelineLayoutWrapper m_copySamplePipelineLayout;
506     std::vector<GraphicsPipelineWrapper> m_copySamplePipelines;
507 
508     Move<VkCommandPool> m_cmdPool;
509     Move<VkCommandBuffer> m_cmdBuffer;
510 
511     std::vector<de::SharedPtr<Allocation>> m_allocations;
512 
513     ImageBackingMode m_backingMode;
514     const float m_depthClearValue;
515     const bool m_useFragmentShadingRate;
516 };
517 
518 class RasterizationSamplesInstance : public vkt::TestInstance
519 {
520 public:
521     RasterizationSamplesInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
522                                  VkPrimitiveTopology topology, float pointSize,
523                                  const std::vector<Vertex4RGBA> &vertices,
524                                  const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
525                                  const VkPipelineColorBlendAttachmentState &blendState, const TestModeFlags modeFlags,
526                                  ImageBackingMode backingMode, const bool useFragmentShadingRate);
~RasterizationSamplesInstance(void)527     virtual ~RasterizationSamplesInstance(void)
528     {
529     }
530 
531     virtual tcu::TestStatus iterate(void);
532 
533 protected:
534     virtual tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &result);
535 
536     const VkFormat m_colorFormat;
537     const tcu::IVec2 m_renderSize;
538     const VkPrimitiveTopology m_primitiveTopology;
539     const float m_pointSize;
540     const std::vector<Vertex4RGBA> m_vertices;
541     const std::vector<Vertex4RGBA> m_fullQuadVertices; //!< used by depth/stencil case
542     const TestModeFlags m_modeFlags;
543     de::MovePtr<MultisampleRenderer> m_multisampleRenderer;
544     const bool m_useFragmentShadingRate;
545 };
546 
547 class MinSampleShadingInstance : public vkt::TestInstance
548 {
549 public:
550     MinSampleShadingInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
551                              VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
552                              const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
553                              const VkPipelineColorBlendAttachmentState &blendState, ImageBackingMode backingMode,
554                              const bool useFragmentShadingRate);
~MinSampleShadingInstance(void)555     virtual ~MinSampleShadingInstance(void)
556     {
557     }
558 
559     virtual tcu::TestStatus iterate(void);
560 
561 protected:
562     virtual tcu::TestStatus verifySampleShadedImage(const std::vector<tcu::TextureLevel> &testShadingImages,
563                                                     const tcu::ConstPixelBufferAccess &noSampleshadingImage);
564 
565     const PipelineConstructionType m_pipelineConstructionType;
566     const VkFormat m_colorFormat;
567     const tcu::IVec2 m_renderSize;
568     const VkPrimitiveTopology m_primitiveTopology;
569     const std::vector<Vertex4RGBA> m_vertices;
570     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
571     const VkPipelineColorBlendAttachmentState m_colorBlendState;
572     const ImageBackingMode m_backingMode;
573     const bool m_useFragmentShadingRate;
574 };
575 
576 class MinSampleShadingDisabledInstance : public MinSampleShadingInstance
577 {
578 public:
579     MinSampleShadingDisabledInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
580                                      VkPrimitiveTopology topology, float pointSize,
581                                      const std::vector<Vertex4RGBA> &vertices,
582                                      const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
583                                      const VkPipelineColorBlendAttachmentState &blendState,
584                                      ImageBackingMode backingMode, const bool useFragmentShadingRate);
~MinSampleShadingDisabledInstance(void)585     virtual ~MinSampleShadingDisabledInstance(void)
586     {
587     }
588 
589 protected:
590     virtual tcu::TestStatus verifySampleShadedImage(const std::vector<tcu::TextureLevel> &sampleShadedImages,
591                                                     const tcu::ConstPixelBufferAccess &noSampleshadingImage);
592 };
593 
594 class SampleMaskInstance : public vkt::TestInstance
595 {
596 public:
597     SampleMaskInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
598                        VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
599                        const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
600                        const VkPipelineColorBlendAttachmentState &blendState, ImageBackingMode backingMode,
601                        const bool useFragmentShadingRate);
~SampleMaskInstance(void)602     virtual ~SampleMaskInstance(void)
603     {
604     }
605 
606     virtual tcu::TestStatus iterate(void);
607 
608 protected:
609     virtual tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &testShadingImage,
610                                         const tcu::ConstPixelBufferAccess &minShadingImage,
611                                         const tcu::ConstPixelBufferAccess &maxShadingImage);
612     const PipelineConstructionType m_pipelineConstructionType;
613     const VkFormat m_colorFormat;
614     const tcu::IVec2 m_renderSize;
615     const VkPrimitiveTopology m_primitiveTopology;
616     const std::vector<Vertex4RGBA> m_vertices;
617     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
618     const VkPipelineColorBlendAttachmentState m_colorBlendState;
619     const ImageBackingMode m_backingMode;
620     const bool m_useFragmentShadingRate;
621 };
622 
623 class AlphaToOneInstance : public vkt::TestInstance
624 {
625 public:
626     AlphaToOneInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
627                        VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
628                        const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
629                        const VkPipelineColorBlendAttachmentState &blendState, ImageBackingMode backingMode,
630                        const bool useFragmentShadingRate);
~AlphaToOneInstance(void)631     virtual ~AlphaToOneInstance(void)
632     {
633     }
634 
635     virtual tcu::TestStatus iterate(void);
636 
637 protected:
638     virtual tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &alphaOneImage,
639                                         const tcu::ConstPixelBufferAccess &noAlphaOneImage);
640     const PipelineConstructionType m_pipelineConstructionType;
641     const VkFormat m_colorFormat;
642     const tcu::IVec2 m_renderSize;
643     const VkPrimitiveTopology m_primitiveTopology;
644     const std::vector<Vertex4RGBA> m_vertices;
645     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
646     const VkPipelineColorBlendAttachmentState m_colorBlendState;
647     const ImageBackingMode m_backingMode;
648     const bool m_useFragmentShadingRate;
649 };
650 
651 class AlphaToCoverageInstance : public vkt::TestInstance
652 {
653 public:
654     AlphaToCoverageInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
655                             VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
656                             const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
657                             const VkPipelineColorBlendAttachmentState &blendState, GeometryType geometryType,
658                             ImageBackingMode backingMode, const bool useFragmentShadingRate,
659                             const bool checkDepthBuffer);
~AlphaToCoverageInstance(void)660     virtual ~AlphaToCoverageInstance(void)
661     {
662     }
663 
664     virtual tcu::TestStatus iterate(void);
665 
666 protected:
667     virtual tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &result);
668     virtual tcu::TestStatus verifyDepthBufferCheck(const tcu::ConstPixelBufferAccess &result);
669 
670     const PipelineConstructionType m_pipelineConstructionType;
671     const VkFormat m_colorFormat;
672     const VkFormat m_depthStencilFormat;
673     const tcu::IVec2 m_renderSize;
674     const VkPrimitiveTopology m_primitiveTopology;
675     const std::vector<Vertex4RGBA> m_vertices;
676     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
677     const VkPipelineColorBlendAttachmentState m_colorBlendState;
678     const GeometryType m_geometryType;
679     const ImageBackingMode m_backingMode;
680     const bool m_useFragmentShadingRate;
681     const bool m_checkDepthBuffer;
682 };
683 
684 class AlphaToCoverageNoColorAttachmentInstance : public vkt::TestInstance
685 {
686 public:
687     AlphaToCoverageNoColorAttachmentInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
688                                              VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
689                                              const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
690                                              const VkPipelineColorBlendAttachmentState &blendState,
691                                              GeometryType geometryType, ImageBackingMode backingMode,
692                                              const bool useFragmentShadingRate);
~AlphaToCoverageNoColorAttachmentInstance(void)693     virtual ~AlphaToCoverageNoColorAttachmentInstance(void)
694     {
695     }
696 
697     virtual tcu::TestStatus iterate(void);
698 
699 protected:
700     virtual tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &result);
701 
702     const PipelineConstructionType m_pipelineConstructionType;
703     const VkFormat m_colorFormat;
704     const VkFormat m_depthStencilFormat;
705     const tcu::IVec2 m_renderSize;
706     const VkPrimitiveTopology m_primitiveTopology;
707     const std::vector<Vertex4RGBA> m_vertices;
708     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
709     const VkPipelineColorBlendAttachmentState m_colorBlendState;
710     const GeometryType m_geometryType;
711     const ImageBackingMode m_backingMode;
712     const bool m_useFragmentShadingRate;
713 };
714 
715 class AlphaToCoverageColorUnusedAttachmentInstance : public vkt::TestInstance
716 {
717 public:
718     AlphaToCoverageColorUnusedAttachmentInstance(Context &context,
719                                                  const PipelineConstructionType pipelineConstructionType,
720                                                  VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
721                                                  const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
722                                                  const VkPipelineColorBlendAttachmentState &blendState,
723                                                  GeometryType geometryType, ImageBackingMode backingMode,
724                                                  const bool useFragmentShadingRate);
~AlphaToCoverageColorUnusedAttachmentInstance(void)725     virtual ~AlphaToCoverageColorUnusedAttachmentInstance(void)
726     {
727     }
728 
729     virtual tcu::TestStatus iterate(void);
730 
731 protected:
732     virtual tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &result);
733 
734     const PipelineConstructionType m_pipelineConstructionType;
735     const VkFormat m_colorFormat;
736     const tcu::IVec2 m_renderSize;
737     const VkPrimitiveTopology m_primitiveTopology;
738     const std::vector<Vertex4RGBA> m_vertices;
739     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
740     const VkPipelineColorBlendAttachmentState m_colorBlendState;
741     const GeometryType m_geometryType;
742     const ImageBackingMode m_backingMode;
743     const bool m_useFragmentShadingRate;
744 };
745 
746 class SampleMaskWithConservativeInstance : public vkt::TestInstance
747 {
748 public:
749     SampleMaskWithConservativeInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
750                                        const VkSampleCountFlagBits rasterizationSamples,
751                                        const bool enableMinSampleShading, const float minSampleShading,
752                                        const bool enableSampleMask, const VkSampleMask sampleMask,
753                                        const VkConservativeRasterizationModeEXT conservativeRasterizationMode,
754                                        const bool enablePostDepthCoverage, const bool enableFullyCoveredEXT,
755                                        const RenderType renderType, const bool useFragmentShadingRate);
~SampleMaskWithConservativeInstance(void)756     ~SampleMaskWithConservativeInstance(void)
757     {
758     }
759 
760     tcu::TestStatus iterate(void);
761 
762 protected:
763     VkPipelineMultisampleStateCreateInfo getMultisampleState(const VkSampleCountFlagBits rasterizationSamples,
764                                                              const bool enableMinSampleShading,
765                                                              const float minSampleShading, const bool enableSampleMask);
766     VkPipelineRasterizationConservativeStateCreateInfoEXT getRasterizationConservativeStateCreateInfo(
767         const VkConservativeRasterizationModeEXT conservativeRasterizationMode);
768     std::vector<Vertex4RGBA> generateVertices(void);
769     tcu::TestStatus verifyImage(const std::vector<tcu::TextureLevel> &sampleShadedImages,
770                                 const tcu::ConstPixelBufferAccess &result);
771 
772     const PipelineConstructionType m_pipelineConstructionType;
773     const VkSampleCountFlagBits m_rasterizationSamples;
774     const bool m_enablePostDepthCoverage;
775     const bool m_enableFullyCoveredEXT;
776     const VkFormat m_colorFormat;
777     const VkFormat m_depthStencilFormat;
778     const tcu::IVec2 m_renderSize;
779     const bool m_useDepth;
780     const bool m_useStencil;
781     const bool m_useConservative;
782     const bool m_useFragmentShadingRate;
783     const VkConservativeRasterizationModeEXT m_conservativeRasterizationMode;
784     const VkPrimitiveTopology m_topology;
785     const tcu::Vec4 m_renderColor;
786     const float m_depthClearValue;
787     const std::vector<Vertex4RGBA> m_vertices;
788     const bool m_enableSampleMask;
789     const std::vector<VkSampleMask> m_sampleMask;
790     const bool m_enableMinSampleShading;
791     const float m_minSampleShading;
792     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
793     const VkPipelineRasterizationConservativeStateCreateInfoEXT m_rasterizationConservativeStateCreateInfo;
794     const VkPipelineColorBlendAttachmentState m_blendState;
795     const RenderType m_renderType;
796     const ImageBackingMode m_imageBackingMode;
797 };
798 
799 #ifndef CTS_USES_VULKANSC
800 class SampleMaskWithDepthTestInstance : public vkt::TestInstance
801 {
802 public:
803     SampleMaskWithDepthTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
804                                     const VkSampleCountFlagBits rasterizationSamples,
805                                     const bool enablePostDepthCoverage, const bool useFragmentShadingRate);
~SampleMaskWithDepthTestInstance(void)806     ~SampleMaskWithDepthTestInstance(void)
807     {
808     }
809 
810     tcu::TestStatus iterate(void);
811 
812 protected:
813     VkPipelineMultisampleStateCreateInfo getMultisampleState(const VkSampleCountFlagBits rasterizationSamples);
814     std::vector<Vertex4RGBA> generateVertices(void);
815     tcu::TestStatus verifyImage(const tcu::ConstPixelBufferAccess &result);
816 
817     struct SampleCoverage
818     {
SampleCoveragevkt::pipeline::__anon85754e250111::SampleMaskWithDepthTestInstance::SampleCoverage819         SampleCoverage()
820         {
821         }
SampleCoveragevkt::pipeline::__anon85754e250111::SampleMaskWithDepthTestInstance::SampleCoverage822         SampleCoverage(uint32_t min_, uint32_t max_) : min(min_), max(max_)
823         {
824         }
825 
826         uint32_t min;
827         uint32_t max;
828     };
829 
830     const PipelineConstructionType m_pipelineConstructionType;
831     const VkSampleCountFlagBits m_rasterizationSamples;
832     const bool m_enablePostDepthCoverage;
833     const VkFormat m_colorFormat;
834     const VkFormat m_depthStencilFormat;
835     const tcu::IVec2 m_renderSize;
836     const bool m_useDepth;
837     const bool m_useStencil;
838     const VkPrimitiveTopology m_topology;
839     const tcu::Vec4 m_renderColor;
840     const std::vector<Vertex4RGBA> m_vertices;
841     const VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
842     const VkPipelineColorBlendAttachmentState m_blendState;
843     const RenderType m_renderType;
844     const ImageBackingMode m_imageBackingMode;
845     const float m_depthClearValue;
846     std::map<VkSampleCountFlagBits, SampleCoverage> m_refCoverageAfterDepthTest;
847     const bool m_useFragmentShadingRate;
848 };
849 
850 // Helper functions
851 
checkSupport(Context & context,MultisampleTestParams params)852 void checkSupport(Context &context, MultisampleTestParams params)
853 {
854     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
855                                           params.pipelineConstructionType);
856 }
857 #endif // CTS_USES_VULKANSC
858 
initMultisamplePrograms(SourceCollections & sources,MultisampleTestParams params)859 void initMultisamplePrograms(SourceCollections &sources, MultisampleTestParams params)
860 {
861     const std::string pointSize = params.geometryType == GEOMETRY_TYPE_OPAQUE_POINT ?
862                                       (std::string("    gl_PointSize = ") + de::toString(params.pointSize) + ".0f;\n") :
863                                       std::string("");
864     std::ostringstream vertexSource;
865 
866     vertexSource << "#version 310 es\n"
867                     "layout(location = 0) in vec4 position;\n"
868                     "layout(location = 1) in vec4 color;\n"
869                     "layout(location = 0) out highp vec4 vtxColor;\n"
870                     "void main (void)\n"
871                     "{\n"
872                     "    gl_Position = position;\n"
873                     "    vtxColor = color;\n"
874                  << pointSize << "}\n";
875 
876     static const char *fragmentSource = "#version 310 es\n"
877                                         "layout(location = 0) in highp vec4 vtxColor;\n"
878                                         "layout(location = 0) out highp vec4 fragColor;\n"
879                                         "void main (void)\n"
880                                         "{\n"
881                                         "    fragColor = vtxColor;\n"
882                                         "}\n";
883 
884     sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
885     sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
886 }
887 
initSampleShadingPrograms(SourceCollections & sources,MultisampleTestParams params,bool minSampleShadingEnabled)888 void initSampleShadingPrograms(SourceCollections &sources, MultisampleTestParams params, bool minSampleShadingEnabled)
889 {
890     {
891         const std::string pointSize =
892             params.geometryType == GEOMETRY_TYPE_OPAQUE_POINT ?
893                 (std::string("    gl_PointSize = ") + de::toString(params.pointSize) + ".0f;\n") :
894                 std::string("");
895         std::ostringstream vertexSource;
896         std::ostringstream fragmentSource;
897 
898         vertexSource << "#version 440\n"
899                         "layout(location = 0) in vec4 position;\n"
900                         "layout(location = 1) in vec4 color;\n"
901                         "void main (void)\n"
902                         "{\n"
903                         "    gl_Position = position;\n"
904                      << pointSize << "}\n";
905 
906         fragmentSource << "#version 440\n"
907                           "layout(location = 0) out highp vec4 fragColor;\n"
908                           "void main (void)\n"
909                           "{\n";
910         if (minSampleShadingEnabled)
911         {
912             fragmentSource
913                 << "    uint sampleId = gl_SampleID;\n"; // Enable sample shading for shader objects by reading gl_SampleID
914         }
915         fragmentSource << "    fragColor = vec4(fract(gl_FragCoord.xy), 0.0, 1.0);\n"
916                           "}\n";
917 
918         sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
919         sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
920     }
921 
922     {
923         static const char *vertexSource = "#version 440\n"
924                                           "void main (void)\n"
925                                           "{\n"
926                                           "    const vec4 positions[4] = vec4[4](\n"
927                                           "        vec4(-1.0, -1.0, 0.0, 1.0),\n"
928                                           "        vec4(-1.0,  1.0, 0.0, 1.0),\n"
929                                           "        vec4( 1.0, -1.0, 0.0, 1.0),\n"
930                                           "        vec4( 1.0,  1.0, 0.0, 1.0)\n"
931                                           "    );\n"
932                                           "    gl_Position = positions[gl_VertexIndex];\n"
933                                           "}\n";
934 
935         static const char *fragmentSource =
936             "#version 440\n"
937             "precision highp float;\n"
938             "layout(location = 0) out highp vec4 fragColor;\n"
939             "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
940             "layout(push_constant) uniform PushConstantsBlock\n"
941             "{\n"
942             "    int sampleId;\n"
943             "} pushConstants;\n"
944             "void main (void)\n"
945             "{\n"
946             "    fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
947             "}\n";
948 
949         sources.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
950         sources.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
951     }
952 }
953 
initAlphaToCoverageColorUnusedAttachmentPrograms(SourceCollections & sources)954 void initAlphaToCoverageColorUnusedAttachmentPrograms(SourceCollections &sources)
955 {
956     std::ostringstream vertexSource;
957 
958     vertexSource << "#version 310 es\n"
959                     "layout(location = 0) in vec4 position;\n"
960                     "layout(location = 1) in vec4 color;\n"
961                     "layout(location = 0) out highp vec4 vtxColor;\n"
962                     "void main (void)\n"
963                     "{\n"
964                     "    gl_Position = position;\n"
965                     "    vtxColor = color;\n"
966                     "}\n";
967 
968     // Location 0 is unused, but the alpha for coverage is written there. Location 1 has no alpha channel.
969     static const char *fragmentSource = "#version 310 es\n"
970                                         "layout(location = 0) in highp vec4 vtxColor;\n"
971                                         "layout(location = 0) out highp vec4 fragColor0;\n"
972                                         "layout(location = 1) out highp vec3 fragColor1;\n"
973                                         "void main (void)\n"
974                                         "{\n"
975                                         "    fragColor0 = vtxColor;\n"
976                                         "    fragColor1 = vtxColor.rgb;\n"
977                                         "}\n";
978 
979     sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
980     sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
981 }
982 
isSupportedSampleCount(const InstanceInterface & instanceInterface,VkPhysicalDevice physicalDevice,VkSampleCountFlagBits rasterizationSamples)983 bool isSupportedSampleCount(const InstanceInterface &instanceInterface, VkPhysicalDevice physicalDevice,
984                             VkSampleCountFlagBits rasterizationSamples)
985 {
986     VkPhysicalDeviceProperties deviceProperties;
987 
988     instanceInterface.getPhysicalDeviceProperties(physicalDevice, &deviceProperties);
989 
990     return !!(deviceProperties.limits.framebufferColorSampleCounts & rasterizationSamples);
991 }
992 
checkFragmentShadingRateRequirements(Context & context,uint32_t sampleCount)993 bool checkFragmentShadingRateRequirements(Context &context, uint32_t sampleCount)
994 {
995     const auto &vki           = context.getInstanceInterface();
996     const auto physicalDevice = context.getPhysicalDevice();
997 
998     context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
999 
1000     if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
1001         TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
1002 
1003     // Fetch information about supported fragment shading rates
1004     uint32_t supportedFragmentShadingRateCount = 0;
1005     vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL);
1006 
1007     std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(
1008         supportedFragmentShadingRateCount,
1009         {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, DE_NULL, vk::VK_SAMPLE_COUNT_1_BIT, {1, 1}});
1010     vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount,
1011                                                  supportedFragmentShadingRates.data());
1012 
1013     for (const auto &rate : supportedFragmentShadingRates)
1014     {
1015         if ((rate.fragmentSize.width == 2u) && (rate.fragmentSize.height == 2u) && (rate.sampleCounts & sampleCount))
1016             return true;
1017     }
1018 
1019     return false;
1020 }
1021 
getDefaultColorBlendAttachmentState()1022 VkPipelineColorBlendAttachmentState getDefaultColorBlendAttachmentState()
1023 {
1024     const VkPipelineColorBlendAttachmentState colorBlendState = {
1025         false,                                                // VkBool32 blendEnable;
1026         VK_BLEND_FACTOR_ONE,                                  // VkBlendFactor srcColorBlendFactor;
1027         VK_BLEND_FACTOR_ZERO,                                 // VkBlendFactor dstColorBlendFactor;
1028         VK_BLEND_OP_ADD,                                      // VkBlendOp colorBlendOp;
1029         VK_BLEND_FACTOR_ONE,                                  // VkBlendFactor srcAlphaBlendFactor;
1030         VK_BLEND_FACTOR_ZERO,                                 // VkBlendFactor dstAlphaBlendFactor;
1031         VK_BLEND_OP_ADD,                                      // VkBlendOp alphaBlendOp;
1032         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
1033             VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1034 
1035     return colorBlendState;
1036 }
1037 
getAlphaToCoverageBlendState(bool blendEnable)1038 VkPipelineColorBlendAttachmentState getAlphaToCoverageBlendState(bool blendEnable)
1039 {
1040     const VkPipelineColorBlendAttachmentState colorBlendState = {
1041         blendEnable,                                          // VkBool32 blendEnable;
1042         VK_BLEND_FACTOR_SRC_ALPHA,                            // VkBlendFactor srcColorBlendFactor;
1043         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                  // VkBlendFactor dstColorBlendFactor;
1044         VK_BLEND_OP_ADD,                                      // VkBlendOp colorBlendOp;
1045         VK_BLEND_FACTOR_ZERO,                                 // VkBlendFactor srcAlphaBlendFactor;
1046         VK_BLEND_FACTOR_ONE,                                  // VkBlendFactor dstAlphaBlendFactor;
1047         VK_BLEND_OP_ADD,                                      // VkBlendOp alphaBlendOp;
1048         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
1049             VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1050 
1051     return colorBlendState;
1052 }
1053 
getUniqueColorsCount(const tcu::ConstPixelBufferAccess & image)1054 uint32_t getUniqueColorsCount(const tcu::ConstPixelBufferAccess &image)
1055 {
1056     DE_ASSERT(image.getFormat().getPixelSize() == 4);
1057 
1058     std::map<uint32_t, uint32_t> histogram; // map<pixel value, number of occurrences>
1059     const uint32_t pixelCount = image.getWidth() * image.getHeight() * image.getDepth();
1060 
1061     for (uint32_t pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
1062     {
1063         const uint32_t pixelValue = *((const uint32_t *)image.getDataPtr() + pixelNdx);
1064 
1065         if (histogram.find(pixelValue) != histogram.end())
1066             histogram[pixelValue]++;
1067         else
1068             histogram[pixelValue] = 1;
1069     }
1070 
1071     return (uint32_t)histogram.size();
1072 }
1073 
getImageAspectFlags(const VkFormat format)1074 VkImageAspectFlags getImageAspectFlags(const VkFormat format)
1075 {
1076     const tcu::TextureFormat tcuFormat = mapVkFormat(format);
1077 
1078     if (tcuFormat.order == tcu::TextureFormat::DS)
1079         return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1080     else if (tcuFormat.order == tcu::TextureFormat::D)
1081         return VK_IMAGE_ASPECT_DEPTH_BIT;
1082     else if (tcuFormat.order == tcu::TextureFormat::S)
1083         return VK_IMAGE_ASPECT_STENCIL_BIT;
1084 
1085     DE_ASSERT(false);
1086     return 0u;
1087 }
1088 
generateVertices(const GeometryType geometryType)1089 std::vector<Vertex4RGBA> generateVertices(const GeometryType geometryType)
1090 {
1091     std::vector<Vertex4RGBA> vertices;
1092 
1093     switch (geometryType)
1094     {
1095     case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
1096     case GEOMETRY_TYPE_INVISIBLE_TRIANGLE:
1097     {
1098         Vertex4RGBA vertexData[3] = {{tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
1099                                      {tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
1100                                      {tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)}};
1101 
1102         if (geometryType == GEOMETRY_TYPE_INVISIBLE_TRIANGLE)
1103         {
1104             for (int i = 0; i < 3; i++)
1105                 vertexData[i].color = tcu::Vec4();
1106         }
1107 
1108         vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 3);
1109         break;
1110     }
1111 
1112     case GEOMETRY_TYPE_OPAQUE_LINE:
1113     {
1114         const Vertex4RGBA vertexData[2] = {{tcu::Vec4(-0.75f, 0.25f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
1115                                            {tcu::Vec4(0.75f, -0.25f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)}};
1116 
1117         vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 2);
1118         break;
1119     }
1120 
1121     case GEOMETRY_TYPE_OPAQUE_POINT:
1122     {
1123         const Vertex4RGBA vertex = {tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)};
1124 
1125         vertices = std::vector<Vertex4RGBA>(1, vertex);
1126         break;
1127     }
1128 
1129     case GEOMETRY_TYPE_OPAQUE_QUAD:
1130     case GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH:
1131     case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
1132     case GEOMETRY_TYPE_INVISIBLE_QUAD:
1133     case GEOMETRY_TYPE_GRADIENT_QUAD:
1134     {
1135         Vertex4RGBA vertexData[4] = {{tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
1136                                      {tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
1137                                      {tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
1138                                      {tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)}};
1139 
1140         if (geometryType == GEOMETRY_TYPE_TRANSLUCENT_QUAD)
1141         {
1142             for (int i = 0; i < 4; i++)
1143                 vertexData[i].color.w() = 0.25f;
1144         }
1145         else if (geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD)
1146         {
1147             for (int i = 0; i < 4; i++)
1148                 vertexData[i].color.w() = 0.0f;
1149         }
1150         else if (geometryType == GEOMETRY_TYPE_GRADIENT_QUAD)
1151         {
1152             vertexData[0].color.w() = 0.0f;
1153             vertexData[2].color.w() = 0.0f;
1154         }
1155         else if (geometryType == GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH)
1156         {
1157             for (int i = 0; i < 4; i++)
1158                 vertexData[i].position.z() = 0.5f;
1159         }
1160 
1161         vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + de::arrayLength(vertexData));
1162         break;
1163     }
1164 
1165     default:
1166         DE_ASSERT(false);
1167     }
1168     return vertices;
1169 }
1170 
getPrimitiveTopology(const GeometryType geometryType)1171 VkPrimitiveTopology getPrimitiveTopology(const GeometryType geometryType)
1172 {
1173     switch (geometryType)
1174     {
1175     case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
1176     case GEOMETRY_TYPE_INVISIBLE_TRIANGLE:
1177         return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1178 
1179     case GEOMETRY_TYPE_OPAQUE_LINE:
1180         return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
1181     case GEOMETRY_TYPE_OPAQUE_POINT:
1182         return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1183 
1184     case GEOMETRY_TYPE_OPAQUE_QUAD:
1185     case GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH:
1186     case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
1187     case GEOMETRY_TYPE_INVISIBLE_QUAD:
1188     case GEOMETRY_TYPE_GRADIENT_QUAD:
1189         return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1190 
1191     default:
1192         DE_ASSERT(false);
1193         return VK_PRIMITIVE_TOPOLOGY_LAST;
1194     }
1195 }
1196 
isSupportedDepthStencilFormat(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkFormat format)1197 bool isSupportedDepthStencilFormat(const InstanceInterface &vki, const VkPhysicalDevice physDevice,
1198                                    const VkFormat format)
1199 {
1200     VkFormatProperties formatProps;
1201     vki.getPhysicalDeviceFormatProperties(physDevice, format, &formatProps);
1202     return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
1203 }
1204 
findSupportedDepthStencilFormat(Context & context,const bool useDepth,const bool useStencil)1205 VkFormat findSupportedDepthStencilFormat(Context &context, const bool useDepth, const bool useStencil)
1206 {
1207     if (useDepth && !useStencil)
1208         return VK_FORMAT_D16_UNORM; // must be supported
1209 
1210     const InstanceInterface &vki      = context.getInstanceInterface();
1211     const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1212 
1213     // One of these formats must be supported.
1214 
1215     if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D24_UNORM_S8_UINT))
1216         return VK_FORMAT_D24_UNORM_S8_UINT;
1217 
1218     if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D32_SFLOAT_S8_UINT))
1219         return VK_FORMAT_D32_SFLOAT_S8_UINT;
1220 
1221     return VK_FORMAT_UNDEFINED;
1222 }
1223 
1224 // MultisampleTest
1225 
MultisampleTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,GeometryType geometryType,float pointSize,ImageBackingMode backingMode,const bool useFragmentShadingRate)1226 MultisampleTest::MultisampleTest(tcu::TestContext &testContext, const std::string &name,
1227                                  const PipelineConstructionType pipelineConstructionType,
1228                                  const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1229                                  const VkPipelineColorBlendAttachmentState &blendState, GeometryType geometryType,
1230                                  float pointSize, ImageBackingMode backingMode, const bool useFragmentShadingRate)
1231     : vkt::TestCase(testContext, name)
1232     , m_pipelineConstructionType(pipelineConstructionType)
1233     , m_multisampleStateParams(multisampleStateParams)
1234     , m_colorBlendState(blendState)
1235     , m_geometryType(geometryType)
1236     , m_pointSize(pointSize)
1237     , m_backingMode(backingMode)
1238     , m_useFragmentShadingRate(useFragmentShadingRate)
1239 {
1240     if (m_multisampleStateParams.pSampleMask)
1241     {
1242         // Copy pSampleMask to avoid dependencies with other classes
1243 
1244         const uint32_t maskCount = deCeilFloatToInt32(float(m_multisampleStateParams.rasterizationSamples) / 32);
1245 
1246         for (uint32_t maskNdx = 0; maskNdx < maskCount; maskNdx++)
1247             m_sampleMask.push_back(m_multisampleStateParams.pSampleMask[maskNdx]);
1248 
1249         m_multisampleStateParams.pSampleMask = m_sampleMask.data();
1250     }
1251 }
1252 
initPrograms(SourceCollections & programCollection) const1253 void MultisampleTest::initPrograms(SourceCollections &programCollection) const
1254 {
1255     MultisampleTestParams params = {m_pipelineConstructionType, m_geometryType, m_pointSize, m_backingMode,
1256                                     m_useFragmentShadingRate};
1257     initMultisamplePrograms(programCollection, params);
1258 }
1259 
createInstance(Context & context) const1260 TestInstance *MultisampleTest::createInstance(Context &context) const
1261 {
1262     return createMultisampleTestInstance(context, getPrimitiveTopology(m_geometryType), m_pointSize,
1263                                          generateVertices(m_geometryType), m_multisampleStateParams, m_colorBlendState);
1264 }
1265 
checkSupport(Context & context) const1266 void MultisampleTest::checkSupport(Context &context) const
1267 {
1268     if (m_geometryType == GEOMETRY_TYPE_OPAQUE_POINT && m_pointSize > 1.0f)
1269         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
1270 
1271     if (m_useFragmentShadingRate &&
1272         !checkFragmentShadingRateRequirements(context, m_multisampleStateParams.rasterizationSamples))
1273         TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1274 
1275     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1276                                           m_pipelineConstructionType);
1277 }
1278 
1279 // RasterizationSamplesTest
1280 
RasterizationSamplesTest(tcu::TestContext & testContext,const std::string & name,PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,GeometryType geometryType,float pointSize,ImageBackingMode backingMode,TestModeFlags modeFlags,const bool useFragmentShadingRate)1281 RasterizationSamplesTest::RasterizationSamplesTest(tcu::TestContext &testContext, const std::string &name,
1282                                                    PipelineConstructionType pipelineConstructionType,
1283                                                    VkSampleCountFlagBits rasterizationSamples,
1284                                                    GeometryType geometryType, float pointSize,
1285                                                    ImageBackingMode backingMode, TestModeFlags modeFlags,
1286                                                    const bool useFragmentShadingRate)
1287     : MultisampleTest(testContext, name, pipelineConstructionType,
1288                       getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(),
1289                       geometryType, pointSize, backingMode, useFragmentShadingRate)
1290     , m_backingMode(backingMode)
1291     , m_modeFlags(modeFlags)
1292 {
1293 }
1294 
getRasterizationSamplesStateParams(VkSampleCountFlagBits rasterizationSamples)1295 VkPipelineMultisampleStateCreateInfo RasterizationSamplesTest::getRasterizationSamplesStateParams(
1296     VkSampleCountFlagBits rasterizationSamples)
1297 {
1298     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1299         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1300         DE_NULL,                                                  // const void* pNext;
1301         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1302         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1303         false,                                                    // VkBool32 sampleShadingEnable;
1304         0.0f,                                                     // float minSampleShading;
1305         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1306         false,                                                    // VkBool32 alphaToCoverageEnable;
1307         false                                                     // VkBool32 alphaToOneEnable;
1308     };
1309 
1310     return multisampleStateParams;
1311 }
1312 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1313 TestInstance *RasterizationSamplesTest::createMultisampleTestInstance(
1314     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1315     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1316     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1317 {
1318     return new RasterizationSamplesInstance(context, m_pipelineConstructionType, topology, pointSize, vertices,
1319                                             multisampleStateParams, colorBlendState, m_modeFlags, m_backingMode,
1320                                             m_useFragmentShadingRate);
1321 }
1322 
1323 // MinSampleShadingTest
1324 
MinSampleShadingTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,float minSampleShading,GeometryType geometryType,float pointSize,ImageBackingMode backingMode,const bool minSampleShadingEnabled,const bool useFragmentShadingRate)1325 MinSampleShadingTest::MinSampleShadingTest(tcu::TestContext &testContext, const std::string &name,
1326                                            const PipelineConstructionType pipelineConstructionType,
1327                                            VkSampleCountFlagBits rasterizationSamples, float minSampleShading,
1328                                            GeometryType geometryType, float pointSize, ImageBackingMode backingMode,
1329                                            const bool minSampleShadingEnabled, const bool useFragmentShadingRate)
1330     : MultisampleTest(testContext, name, pipelineConstructionType,
1331                       getMinSampleShadingStateParams(rasterizationSamples, minSampleShading, minSampleShadingEnabled),
1332                       getDefaultColorBlendAttachmentState(), geometryType, pointSize, backingMode,
1333                       useFragmentShadingRate)
1334     , m_pointSize(pointSize)
1335     , m_backingMode(backingMode)
1336     , m_minSampleShadingEnabled(minSampleShadingEnabled)
1337 {
1338 }
1339 
checkSupport(Context & context) const1340 void MinSampleShadingTest::checkSupport(Context &context) const
1341 {
1342     MultisampleTest::checkSupport(context);
1343 
1344     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1345 }
1346 
initPrograms(SourceCollections & programCollection) const1347 void MinSampleShadingTest::initPrograms(SourceCollections &programCollection) const
1348 {
1349     MultisampleTestParams params = {m_pipelineConstructionType, m_geometryType, m_pointSize, m_backingMode,
1350                                     m_useFragmentShadingRate};
1351     initSampleShadingPrograms(programCollection, params, m_minSampleShadingEnabled);
1352 }
1353 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1354 TestInstance *MinSampleShadingTest::createMultisampleTestInstance(
1355     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1356     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1357     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1358 {
1359     if (m_minSampleShadingEnabled)
1360         return new MinSampleShadingInstance(context, m_pipelineConstructionType, topology, pointSize, vertices,
1361                                             multisampleStateParams, colorBlendState, m_backingMode,
1362                                             m_useFragmentShadingRate);
1363     else
1364         return new MinSampleShadingDisabledInstance(context, m_pipelineConstructionType, topology, pointSize, vertices,
1365                                                     multisampleStateParams, colorBlendState, m_backingMode,
1366                                                     m_useFragmentShadingRate);
1367 }
1368 
getMinSampleShadingStateParams(VkSampleCountFlagBits rasterizationSamples,float minSampleShading,bool minSampleShadingEnabled)1369 VkPipelineMultisampleStateCreateInfo MinSampleShadingTest::getMinSampleShadingStateParams(
1370     VkSampleCountFlagBits rasterizationSamples, float minSampleShading, bool minSampleShadingEnabled)
1371 {
1372     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1373         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1374         DE_NULL,                                                  // const void* pNext;
1375         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1376         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1377         minSampleShadingEnabled ? VK_TRUE : VK_FALSE,             // VkBool32 sampleShadingEnable;
1378         minSampleShading,                                         // float minSampleShading;
1379         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1380         false,                                                    //  VkBool32 alphaToCoverageEnable;
1381         false                                                     //  VkBool32 alphaToOneEnable;
1382     };
1383 
1384     return multisampleStateParams;
1385 }
1386 
1387 // SampleMaskTest
1388 
SampleMaskTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,const std::vector<VkSampleMask> & sampleMask,GeometryType geometryType,float pointSize,ImageBackingMode backingMode,const bool useFragmentShadingRate)1389 SampleMaskTest::SampleMaskTest(tcu::TestContext &testContext, const std::string &name,
1390                                const PipelineConstructionType pipelineConstructionType,
1391                                VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask> &sampleMask,
1392                                GeometryType geometryType, float pointSize, ImageBackingMode backingMode,
1393                                const bool useFragmentShadingRate)
1394     : MultisampleTest(testContext, name, pipelineConstructionType,
1395                       getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(),
1396                       geometryType, pointSize, backingMode, useFragmentShadingRate)
1397     , m_backingMode(backingMode)
1398 {
1399 }
1400 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1401 TestInstance *SampleMaskTest::createMultisampleTestInstance(
1402     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1403     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1404     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1405 {
1406     DE_UNREF(pointSize);
1407     return new SampleMaskInstance(context, m_pipelineConstructionType, topology, pointSize, vertices,
1408                                   multisampleStateParams, colorBlendState, m_backingMode, m_useFragmentShadingRate);
1409 }
1410 
getSampleMaskStateParams(VkSampleCountFlagBits rasterizationSamples,const std::vector<VkSampleMask> & sampleMask)1411 VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams(
1412     VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask> &sampleMask)
1413 {
1414     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1415         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1416         DE_NULL,                                                  // const void* pNext;
1417         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1418         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1419         false,                                                    // VkBool32 sampleShadingEnable;
1420         0.0f,                                                     // float minSampleShading;
1421         sampleMask.data(),                                        // const VkSampleMask* pSampleMask;
1422         false,                                                    // VkBool32 alphaToCoverageEnable;
1423         false                                                     // VkBool32 alphaToOneEnable;
1424     };
1425 
1426     return multisampleStateParams;
1427 }
1428 
1429 // AlphaToOneTest
1430 
AlphaToOneTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,ImageBackingMode backingMode,const bool useFragmentShadingRate)1431 AlphaToOneTest::AlphaToOneTest(tcu::TestContext &testContext, const std::string &name,
1432                                const PipelineConstructionType pipelineConstructionType,
1433                                VkSampleCountFlagBits rasterizationSamples, ImageBackingMode backingMode,
1434                                const bool useFragmentShadingRate)
1435     : MultisampleTest(testContext, name, pipelineConstructionType, getAlphaToOneStateParams(rasterizationSamples),
1436                       getAlphaToOneBlendState(), GEOMETRY_TYPE_GRADIENT_QUAD, 1.0f, backingMode, useFragmentShadingRate)
1437     , m_backingMode(backingMode)
1438 {
1439 }
1440 
checkSupport(Context & context) const1441 void AlphaToOneTest::checkSupport(Context &context) const
1442 {
1443     MultisampleTest::checkSupport(context);
1444 
1445     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_ALPHA_TO_ONE);
1446 }
1447 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1448 TestInstance *AlphaToOneTest::createMultisampleTestInstance(
1449     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1450     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1451     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1452 {
1453     DE_UNREF(pointSize);
1454     return new AlphaToOneInstance(context, m_pipelineConstructionType, topology, vertices, multisampleStateParams,
1455                                   colorBlendState, m_backingMode, m_useFragmentShadingRate);
1456 }
1457 
getAlphaToOneStateParams(VkSampleCountFlagBits rasterizationSamples)1458 VkPipelineMultisampleStateCreateInfo AlphaToOneTest::getAlphaToOneStateParams(
1459     VkSampleCountFlagBits rasterizationSamples)
1460 {
1461     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1462         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1463         DE_NULL,                                                  // const void* pNext;
1464         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1465         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1466         false,                                                    // VkBool32 sampleShadingEnable;
1467         0.0f,                                                     // float minSampleShading;
1468         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1469         false,                                                    // VkBool32 alphaToCoverageEnable;
1470         true                                                      // VkBool32 alphaToOneEnable;
1471     };
1472 
1473     return multisampleStateParams;
1474 }
1475 
getAlphaToOneBlendState(void)1476 VkPipelineColorBlendAttachmentState AlphaToOneTest::getAlphaToOneBlendState(void)
1477 {
1478     const VkPipelineColorBlendAttachmentState colorBlendState = {
1479         true,                                                 // VkBool32 blendEnable;
1480         VK_BLEND_FACTOR_SRC_ALPHA,                            // VkBlendFactor srcColorBlendFactor;
1481         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                  // VkBlendFactor dstColorBlendFactor;
1482         VK_BLEND_OP_ADD,                                      // VkBlendOp colorBlendOp;
1483         VK_BLEND_FACTOR_SRC_ALPHA,                            // VkBlendFactor srcAlphaBlendFactor;
1484         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                  // VkBlendFactor dstAlphaBlendFactor;
1485         VK_BLEND_OP_ADD,                                      // VkBlendOp alphaBlendOp;
1486         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
1487             VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1488 
1489     return colorBlendState;
1490 }
1491 
1492 // AlphaToCoverageTest
1493 
AlphaToCoverageTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,GeometryType geometryType,ImageBackingMode backingMode,const bool useFragmentShadingRate,const bool checkDepthBuffer)1494 AlphaToCoverageTest::AlphaToCoverageTest(tcu::TestContext &testContext, const std::string &name,
1495                                          const PipelineConstructionType pipelineConstructionType,
1496                                          VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType,
1497                                          ImageBackingMode backingMode, const bool useFragmentShadingRate,
1498                                          const bool checkDepthBuffer)
1499     : MultisampleTest(testContext, name, pipelineConstructionType, getAlphaToCoverageStateParams(rasterizationSamples),
1500                       getAlphaToCoverageBlendState(checkDepthBuffer), geometryType, 1.0f, backingMode,
1501                       useFragmentShadingRate)
1502     , m_geometryType(geometryType)
1503     , m_backingMode(backingMode)
1504     , m_checkDepthBuffer(checkDepthBuffer)
1505 {
1506     if (checkDepthBuffer)
1507         DE_ASSERT(geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD);
1508 }
1509 
initPrograms(SourceCollections & programCollection) const1510 void AlphaToCoverageTest::initPrograms(SourceCollections &programCollection) const
1511 {
1512     MultisampleTest::initPrograms(programCollection);
1513 
1514     if (m_checkDepthBuffer)
1515     {
1516         std::ostringstream vert;
1517         vert << "#version 460\n"
1518              << "layout (push_constant, std430) uniform PushConstantBlock { float depth; } pc;\n"
1519              << "layout (location=0) out vec4 vtxColor;\n"
1520              << "vec2 positions[3] = vec2[](\n"
1521              << "    vec2(-1.0, -1.0),\n"
1522              << "    vec2(-1.0, 3.0),\n"
1523              << "    vec2(3.0, -1.0)\n"
1524              << ");\n"
1525              << "void main (void) {\n"
1526              << "    gl_Position = vec4(positions[gl_VertexIndex % 3], pc.depth, 1.0);\n"
1527              << "    vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1528              << "}\n";
1529         programCollection.glslSources.add("checkDepth-vert") << glu::VertexSource(vert.str());
1530     }
1531 }
1532 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1533 TestInstance *AlphaToCoverageTest::createMultisampleTestInstance(
1534     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1535     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1536     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1537 {
1538     DE_UNREF(pointSize);
1539     return new AlphaToCoverageInstance(context, m_pipelineConstructionType, topology, vertices, multisampleStateParams,
1540                                        colorBlendState, m_geometryType, m_backingMode, m_useFragmentShadingRate,
1541                                        m_checkDepthBuffer);
1542 }
1543 
getAlphaToCoverageStateParams(VkSampleCountFlagBits rasterizationSamples)1544 VkPipelineMultisampleStateCreateInfo AlphaToCoverageTest::getAlphaToCoverageStateParams(
1545     VkSampleCountFlagBits rasterizationSamples)
1546 {
1547     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1548         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1549         DE_NULL,                                                  // const void* pNext;
1550         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1551         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1552         false,                                                    // VkBool32 sampleShadingEnable;
1553         0.0f,                                                     // float minSampleShading;
1554         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1555         true,                                                     // VkBool32 alphaToCoverageEnable;
1556         false                                                     // VkBool32 alphaToOneEnable;
1557     };
1558 
1559     return multisampleStateParams;
1560 }
1561 
1562 // AlphaToCoverageNoColorAttachmentTest
1563 
AlphaToCoverageNoColorAttachmentTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,GeometryType geometryType,ImageBackingMode backingMode,const bool useFragmentShadingRate)1564 AlphaToCoverageNoColorAttachmentTest::AlphaToCoverageNoColorAttachmentTest(
1565     tcu::TestContext &testContext, const std::string &name, const PipelineConstructionType pipelineConstructionType,
1566     VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType, ImageBackingMode backingMode,
1567     const bool useFragmentShadingRate)
1568     : MultisampleTest(testContext, name, pipelineConstructionType, getStateParams(rasterizationSamples),
1569                       getDefaultColorBlendAttachmentState(), geometryType, 1.0f, backingMode, useFragmentShadingRate)
1570     , m_geometryType(geometryType)
1571     , m_backingMode(backingMode)
1572 {
1573 }
1574 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1575 TestInstance *AlphaToCoverageNoColorAttachmentTest::createMultisampleTestInstance(
1576     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1577     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1578     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1579 {
1580     DE_UNREF(pointSize);
1581     return new AlphaToCoverageNoColorAttachmentInstance(context, m_pipelineConstructionType, topology, vertices,
1582                                                         multisampleStateParams, colorBlendState, m_geometryType,
1583                                                         m_backingMode, m_useFragmentShadingRate);
1584 }
1585 
getStateParams(VkSampleCountFlagBits rasterizationSamples)1586 VkPipelineMultisampleStateCreateInfo AlphaToCoverageNoColorAttachmentTest::getStateParams(
1587     VkSampleCountFlagBits rasterizationSamples)
1588 {
1589     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1590         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1591         DE_NULL,                                                  // const void* pNext;
1592         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1593         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1594         false,                                                    // VkBool32 sampleShadingEnable;
1595         0.0f,                                                     // float minSampleShading;
1596         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1597         true,                                                     // VkBool32 alphaToCoverageEnable;
1598         false                                                     // VkBool32 alphaToOneEnable;
1599     };
1600 
1601     return multisampleStateParams;
1602 }
1603 
1604 // AlphaToCoverageColorUnusedAttachmentTest
1605 
AlphaToCoverageColorUnusedAttachmentTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,VkSampleCountFlagBits rasterizationSamples,GeometryType geometryType,ImageBackingMode backingMode,const bool useFragmentShadingRate)1606 AlphaToCoverageColorUnusedAttachmentTest::AlphaToCoverageColorUnusedAttachmentTest(
1607     tcu::TestContext &testContext, const std::string &name, const PipelineConstructionType pipelineConstructionType,
1608     VkSampleCountFlagBits rasterizationSamples, GeometryType geometryType, ImageBackingMode backingMode,
1609     const bool useFragmentShadingRate)
1610     : MultisampleTest(testContext, name, pipelineConstructionType, getStateParams(rasterizationSamples),
1611                       getDefaultColorBlendAttachmentState(), geometryType, 1.0f, backingMode, useFragmentShadingRate)
1612     , m_geometryType(geometryType)
1613     , m_backingMode(backingMode)
1614 {
1615 }
1616 
initPrograms(SourceCollections & programCollection) const1617 void AlphaToCoverageColorUnusedAttachmentTest::initPrograms(SourceCollections &programCollection) const
1618 {
1619     initAlphaToCoverageColorUnusedAttachmentPrograms(programCollection);
1620 }
1621 
createMultisampleTestInstance(Context & context,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState) const1622 TestInstance *AlphaToCoverageColorUnusedAttachmentTest::createMultisampleTestInstance(
1623     Context &context, VkPrimitiveTopology topology, float pointSize, const std::vector<Vertex4RGBA> &vertices,
1624     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1625     const VkPipelineColorBlendAttachmentState &colorBlendState) const
1626 {
1627     DE_UNREF(pointSize);
1628     return new AlphaToCoverageColorUnusedAttachmentInstance(context, m_pipelineConstructionType, topology, vertices,
1629                                                             multisampleStateParams, colorBlendState, m_geometryType,
1630                                                             m_backingMode, m_useFragmentShadingRate);
1631 }
1632 
getStateParams(VkSampleCountFlagBits rasterizationSamples)1633 VkPipelineMultisampleStateCreateInfo AlphaToCoverageColorUnusedAttachmentTest::getStateParams(
1634     VkSampleCountFlagBits rasterizationSamples)
1635 {
1636     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1637         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1638         DE_NULL,                                                  // const void* pNext;
1639         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1640         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
1641         false,                                                    // VkBool32 sampleShadingEnable;
1642         0.0f,                                                     // float minSampleShading;
1643         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1644         true,                                                     // VkBool32 alphaToCoverageEnable;
1645         false                                                     // VkBool32 alphaToOneEnable;
1646     };
1647 
1648     return multisampleStateParams;
1649 }
1650 
1651 // SampleMaskWithConservativeTest
SampleMaskWithConservativeTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const VkSampleCountFlagBits rasterizationSamples,const VkConservativeRasterizationModeEXT conservativeRasterizationMode,const bool enableMinSampleShading,const float minSampleShading,const bool enableSampleMask,const VkSampleMask sampleMask,const bool enablePostDepthCoverage,const bool useFragmentShadingRate)1652 SampleMaskWithConservativeTest::SampleMaskWithConservativeTest(
1653     tcu::TestContext &testContext, const std::string &name, const PipelineConstructionType pipelineConstructionType,
1654     const VkSampleCountFlagBits rasterizationSamples,
1655     const VkConservativeRasterizationModeEXT conservativeRasterizationMode, const bool enableMinSampleShading,
1656     const float minSampleShading, const bool enableSampleMask, const VkSampleMask sampleMask,
1657     const bool enablePostDepthCoverage, const bool useFragmentShadingRate)
1658     : vkt::TestCase(testContext, name)
1659     , m_pipelineConstructionType(pipelineConstructionType)
1660     , m_rasterizationSamples(rasterizationSamples)
1661     , m_enableMinSampleShading(enableMinSampleShading)
1662     , m_minSampleShading(minSampleShading)
1663     , m_enableSampleMask(enableSampleMask)
1664     , m_sampleMask(sampleMask)
1665     , m_conservativeRasterizationMode(conservativeRasterizationMode)
1666     , m_enablePostDepthCoverage(enablePostDepthCoverage)
1667     , m_renderType(RENDER_TYPE_RESOLVE)
1668     , m_useFragmentShadingRate(useFragmentShadingRate)
1669 {
1670 }
1671 
checkSupport(Context & context) const1672 void SampleMaskWithConservativeTest::checkSupport(Context &context) const
1673 {
1674     if (!context.getDeviceProperties().limits.standardSampleLocations)
1675         TCU_THROW(NotSupportedError, "standardSampleLocations required");
1676 
1677     if (m_useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, m_rasterizationSamples))
1678         TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1679 
1680     context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
1681 
1682     const auto &conservativeRasterizationProperties = context.getConservativeRasterizationPropertiesEXT();
1683     const uint32_t subPixelPrecisionBits            = context.getDeviceProperties().limits.subPixelPrecisionBits;
1684     const uint32_t subPixelPrecision                = (1 << subPixelPrecisionBits);
1685     const float primitiveOverestimationSizeMult =
1686         float(subPixelPrecision) * conservativeRasterizationProperties.primitiveOverestimationSize;
1687 
1688     DE_ASSERT(subPixelPrecisionBits < sizeof(uint32_t) * 8);
1689 
1690     if (m_enablePostDepthCoverage)
1691     {
1692         context.requireDeviceFunctionality("VK_EXT_post_depth_coverage");
1693         if (!conservativeRasterizationProperties.conservativeRasterizationPostDepthCoverage)
1694             TCU_THROW(NotSupportedError, "conservativeRasterizationPostDepthCoverage not supported");
1695     }
1696 
1697     context.getTestContext().getLog() << tcu::TestLog::Message << "maxExtraPrimitiveOverestimationSize="
1698                                       << conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize << '\n'
1699                                       << "extraPrimitiveOverestimationSizeGranularity="
1700                                       << conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity
1701                                       << '\n'
1702                                       << "degenerateTrianglesRasterized="
1703                                       << conservativeRasterizationProperties.degenerateTrianglesRasterized << '\n'
1704                                       << "primitiveOverestimationSize="
1705                                       << conservativeRasterizationProperties.primitiveOverestimationSize
1706                                       << " (==" << primitiveOverestimationSizeMult << '/' << subPixelPrecision << ")\n"
1707                                       << tcu::TestLog::EndMessage;
1708 
1709     if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT)
1710     {
1711         if (conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity >
1712             conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize)
1713             TCU_FAIL("Granularity cannot be greater than maximum extra size");
1714     }
1715     else if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
1716     {
1717         if (conservativeRasterizationProperties.primitiveUnderestimation == false)
1718             TCU_THROW(NotSupportedError, "Underestimation is not supported");
1719     }
1720     else
1721         TCU_THROW(InternalError, "Non-conservative mode tests are not supported by this class");
1722 
1723     if (!conservativeRasterizationProperties.fullyCoveredFragmentShaderInputVariable)
1724     {
1725         TCU_THROW(NotSupportedError, "FullyCoveredEXT input variable is not supported");
1726     }
1727 
1728     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1729                                           m_pipelineConstructionType);
1730 }
1731 
initPrograms(SourceCollections & programCollection) const1732 void SampleMaskWithConservativeTest::initPrograms(SourceCollections &programCollection) const
1733 {
1734     {
1735         DE_ASSERT((int)m_rasterizationSamples <= 32);
1736 
1737         static const char *vertexSource = "#version 440\n"
1738                                           "layout(location = 0) in vec4 position;\n"
1739                                           "layout(location = 1) in vec4 color;\n"
1740                                           "layout(location = 0) out vec4 vtxColor;\n"
1741                                           "out gl_PerVertex\n"
1742                                           "{\n"
1743                                           "    vec4 gl_Position;\n"
1744                                           "};\n"
1745                                           "\n"
1746                                           "void main (void)\n"
1747                                           "{\n"
1748                                           "    gl_Position = position;\n"
1749                                           "    vtxColor = color;\n"
1750                                           "}\n";
1751 
1752         std::ostringstream fragmentSource;
1753         fragmentSource << "#version 440\n"
1754                        << (m_enablePostDepthCoverage ? "#extension GL_ARB_post_depth_coverage : require\n" : "")
1755                        << (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT ?
1756                                "#extension GL_NV_conservative_raster_underestimation : enable\n" :
1757                                "")
1758                        << "layout(early_fragment_tests) in;\n"
1759                        << (m_enablePostDepthCoverage ? "layout(post_depth_coverage) in;\n" : "")
1760                        << "layout(location = 0) in vec4 vtxColor;\n"
1761                           "layout(location = 0) out vec4 fragColor;\n"
1762                           "void main (void)\n"
1763                           "{\n";
1764         if (m_enableMinSampleShading)
1765         {
1766             fragmentSource << "    const int coveredSamples = bitCount(gl_SampleMaskIn[0]);\n"
1767                               "    fragColor = vtxColor * (1.0 / "
1768                            << (int32_t)m_rasterizationSamples << " * coveredSamples);\n";
1769         }
1770         else if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
1771         {
1772             fragmentSource << "    fragColor = gl_FragFullyCoveredNV ? vtxColor : vec4(0.0f);\n";
1773         }
1774         else
1775         {
1776             fragmentSource << "    fragColor = vtxColor;\n";
1777         }
1778         fragmentSource << "}\n";
1779 
1780         programCollection.glslSources.add("color_vert") << glu::VertexSource(vertexSource);
1781         programCollection.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
1782     }
1783 
1784     {
1785         static const char *vertexSource = "#version 440\n"
1786                                           "void main (void)\n"
1787                                           "{\n"
1788                                           "    const vec4 positions[4] = vec4[4](\n"
1789                                           "        vec4(-1.0, -1.0, 0.0, 1.0),\n"
1790                                           "        vec4(-1.0,  1.0, 0.0, 1.0),\n"
1791                                           "        vec4( 1.0, -1.0, 0.0, 1.0),\n"
1792                                           "        vec4( 1.0,  1.0, 0.0, 1.0)\n"
1793                                           "    );\n"
1794                                           "    gl_Position = positions[gl_VertexIndex];\n"
1795                                           "}\n";
1796 
1797         static const char *fragmentSource =
1798             "#version 440\n"
1799             "precision highp float;\n"
1800             "layout(location = 0) out highp vec4 fragColor;\n"
1801             "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
1802             "layout(push_constant) uniform PushConstantsBlock\n"
1803             "{\n"
1804             "    int sampleId;\n"
1805             "} pushConstants;\n"
1806             "void main (void)\n"
1807             "{\n"
1808             "    fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
1809             "}\n";
1810 
1811         programCollection.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
1812         programCollection.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
1813     }
1814 }
1815 
createInstance(Context & context) const1816 TestInstance *SampleMaskWithConservativeTest::createInstance(Context &context) const
1817 {
1818     return new SampleMaskWithConservativeInstance(
1819         context, m_pipelineConstructionType, m_rasterizationSamples, m_enableMinSampleShading, m_minSampleShading,
1820         m_enableSampleMask, m_sampleMask, m_conservativeRasterizationMode, m_enablePostDepthCoverage, true,
1821         m_renderType, m_useFragmentShadingRate);
1822 }
1823 
1824 // SampleMaskWithDepthTestTest
1825 #ifndef CTS_USES_VULKANSC
SampleMaskWithDepthTestTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const VkSampleCountFlagBits rasterizationSamples,const bool enablePostDepthCoverage,const bool useFragmentShadingRate)1826 SampleMaskWithDepthTestTest::SampleMaskWithDepthTestTest(tcu::TestContext &testContext, const std::string &name,
1827                                                          const PipelineConstructionType pipelineConstructionType,
1828                                                          const VkSampleCountFlagBits rasterizationSamples,
1829                                                          const bool enablePostDepthCoverage,
1830                                                          const bool useFragmentShadingRate)
1831     : vkt::TestCase(testContext, name)
1832     , m_pipelineConstructionType(pipelineConstructionType)
1833     , m_rasterizationSamples(rasterizationSamples)
1834     , m_enablePostDepthCoverage(enablePostDepthCoverage)
1835     , m_useFragmentShadingRate(useFragmentShadingRate)
1836 {
1837 }
1838 
checkSupport(Context & context) const1839 void SampleMaskWithDepthTestTest::checkSupport(Context &context) const
1840 {
1841     if (!context.getDeviceProperties().limits.standardSampleLocations)
1842         TCU_THROW(NotSupportedError, "standardSampleLocations required");
1843 
1844     context.requireDeviceFunctionality("VK_EXT_post_depth_coverage");
1845 
1846     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1847                                           m_pipelineConstructionType);
1848 
1849     if (m_useFragmentShadingRate)
1850     {
1851         if (!context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderSampleMask)
1852             TCU_THROW(NotSupportedError, "fragmentShadingRateWithShaderSampleMask not supported");
1853 
1854         if (!checkFragmentShadingRateRequirements(context, m_rasterizationSamples))
1855             TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1856     }
1857 }
1858 
initPrograms(SourceCollections & programCollection) const1859 void SampleMaskWithDepthTestTest::initPrograms(SourceCollections &programCollection) const
1860 {
1861     DE_ASSERT((int)m_rasterizationSamples <= 32);
1862 
1863     static const char *vertexSource = "#version 440\n"
1864                                       "layout(location = 0) in vec4 position;\n"
1865                                       "layout(location = 1) in vec4 color;\n"
1866                                       "layout(location = 0) out vec4 vtxColor;\n"
1867                                       "out gl_PerVertex\n"
1868                                       "{\n"
1869                                       "    vec4 gl_Position;\n"
1870                                       "};\n"
1871                                       "\n"
1872                                       "void main (void)\n"
1873                                       "{\n"
1874                                       "    gl_Position = position;\n"
1875                                       "    vtxColor = color;\n"
1876                                       "}\n";
1877 
1878     uint32_t samplesPerFragment = m_rasterizationSamples;
1879     if (m_useFragmentShadingRate)
1880     {
1881         // When FSR coverage is enabled the tests uses a pipeline FSR rate of {2,2},
1882         // which means each fragment shader invocation covers 4 pixels.
1883         samplesPerFragment *= 4;
1884 
1885         if (!m_enablePostDepthCoverage)
1886             // For the 4 specific pixels this tests verifies, the primitive
1887             // drawn by the test fully covers 3 of those pixels and
1888             // partially covers 1 of them. When the fragment shader executes
1889             // for those 4 pixels the non-PostDepthCoverage sample mask
1890             // (the sample mask before the depth test) will only have
1891             // 7/8 of the samples set since the last 1/8 is not even covered
1892             // by the primitive.
1893             samplesPerFragment -= m_rasterizationSamples / 2;
1894     }
1895 
1896     std::ostringstream fragmentSource;
1897     fragmentSource << "#version 440\n"
1898                    << (m_enablePostDepthCoverage ? "#extension GL_ARB_post_depth_coverage : require\n" : "")
1899                    << "layout(early_fragment_tests) in;\n"
1900                    << (m_enablePostDepthCoverage ? "layout(post_depth_coverage) in;\n" : "")
1901                    << "layout(location = 0) in vec4 vtxColor;\n"
1902                       "layout(location = 0) out vec4 fragColor;\n"
1903                       "void main (void)\n"
1904                       "{\n"
1905                       "    const int coveredSamples = bitCount(gl_SampleMaskIn[0]);\n"
1906                       "    fragColor = vtxColor * (1.0 / "
1907                    << samplesPerFragment
1908                    << " * coveredSamples);\n"
1909                       "}\n";
1910 
1911     programCollection.glslSources.add("color_vert") << glu::VertexSource(vertexSource);
1912     programCollection.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
1913 }
1914 
createInstance(Context & context) const1915 TestInstance *SampleMaskWithDepthTestTest::createInstance(Context &context) const
1916 {
1917     return new SampleMaskWithDepthTestInstance(context, m_pipelineConstructionType, m_rasterizationSamples,
1918                                                m_enablePostDepthCoverage, m_useFragmentShadingRate);
1919 }
1920 #endif // CTS_USES_VULKANSC
1921 
1922 // RasterizationSamplesInstance
1923 
RasterizationSamplesInstance(Context & context,PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,const TestModeFlags modeFlags,ImageBackingMode backingMode,const bool useFragmentShadingRate)1924 RasterizationSamplesInstance::RasterizationSamplesInstance(
1925     Context &context, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology topology, float pointSize,
1926     const std::vector<Vertex4RGBA> &vertices, const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
1927     const VkPipelineColorBlendAttachmentState &blendState, const TestModeFlags modeFlags, ImageBackingMode backingMode,
1928     const bool useFragmentShadingRate)
1929     : vkt::TestInstance(context)
1930     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
1931     , m_renderSize(32, 32)
1932     , m_primitiveTopology(topology)
1933     , m_pointSize(pointSize)
1934     , m_vertices(vertices)
1935     , m_fullQuadVertices(generateVertices(GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH))
1936     , m_modeFlags(modeFlags)
1937     , m_useFragmentShadingRate(useFragmentShadingRate)
1938 {
1939     if (m_modeFlags != 0)
1940     {
1941         const bool useDepth               = (m_modeFlags & TEST_MODE_DEPTH_BIT) != 0;
1942         const bool useStencil             = (m_modeFlags & TEST_MODE_STENCIL_BIT) != 0;
1943         const VkFormat depthStencilFormat = findSupportedDepthStencilFormat(context, useDepth, useStencil);
1944 
1945         if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1946             TCU_THROW(NotSupportedError, "Required depth/stencil format is not supported");
1947 
1948         const VkPrimitiveTopology pTopology[2]      = {m_primitiveTopology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP};
1949         const std::vector<Vertex4RGBA> pVertices[2] = {m_vertices, m_fullQuadVertices};
1950 
1951         m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
1952             new MultisampleRenderer(context, pipelineConstructionType, m_colorFormat, depthStencilFormat, m_renderSize,
1953                                     useDepth, useStencil, 2u, pTopology, pVertices, multisampleStateParams, blendState,
1954                                     RENDER_TYPE_RESOLVE, backingMode, m_useFragmentShadingRate));
1955     }
1956     else
1957     {
1958         m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(new MultisampleRenderer(
1959             context, pipelineConstructionType, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams,
1960             blendState, RENDER_TYPE_RESOLVE, backingMode, m_useFragmentShadingRate));
1961     }
1962 }
1963 
iterate(void)1964 tcu::TestStatus RasterizationSamplesInstance::iterate(void)
1965 {
1966     de::MovePtr<tcu::TextureLevel> level(m_multisampleRenderer->render());
1967     return verifyImage(level->getAccess());
1968 }
1969 
verifyImage(const tcu::ConstPixelBufferAccess & result)1970 tcu::TestStatus RasterizationSamplesInstance::verifyImage(const tcu::ConstPixelBufferAccess &result)
1971 {
1972     // Verify range of unique pixels
1973     {
1974         const uint32_t numUniqueColors = getUniqueColorsCount(result);
1975         const uint32_t minUniqueColors =
1976             (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_pointSize == 1.0f) ? 2 : 3;
1977 
1978         tcu::TestLog &log = m_context.getTestContext().getLog();
1979 
1980         log << tcu::TestLog::Message << "\nMin. unique colors expected: " << minUniqueColors << "\n"
1981             << "Unique colors found: " << numUniqueColors << "\n"
1982             << tcu::TestLog::EndMessage;
1983 
1984         if (numUniqueColors < minUniqueColors)
1985             return tcu::TestStatus::fail("Unique colors out of expected bounds");
1986     }
1987 
1988     // Verify shape of the rendered primitive (fuzzy-compare)
1989     {
1990         const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1991         const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
1992         const ColorVertexShader vertexShader;
1993         const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
1994         const rr::Program program(&vertexShader, &fragmentShader);
1995         ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1996         rr::RenderState renderState(refRenderer.getViewportState(),
1997                                     m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1998 
1999         if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
2000         {
2001             VkPhysicalDeviceProperties deviceProperties;
2002 
2003             m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(),
2004                                                                          &deviceProperties);
2005 
2006             // gl_PointSize is clamped to pointSizeRange
2007             renderState.point.pointSize = deFloatMin(m_pointSize, deviceProperties.limits.pointSizeRange[1]);
2008         }
2009 
2010         if (m_modeFlags == 0)
2011         {
2012             refRenderer.colorClear(tcu::Vec4(0.0f));
2013             refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
2014         }
2015         else
2016         {
2017             // For depth/stencil case the primitive is invisible and the surroundings are filled red.
2018             refRenderer.colorClear(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
2019             refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
2020         }
2021 
2022         if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "FuzzyImageCompare", "Image comparison",
2023                                refRenderer.getAccess(), result, 0.05f, tcu::COMPARE_LOG_RESULT))
2024             return tcu::TestStatus::fail("Primitive has unexpected shape");
2025     }
2026 
2027     return tcu::TestStatus::pass("Primitive rendered, unique colors within expected bounds");
2028 }
2029 
2030 // MinSampleShadingInstance
2031 
MinSampleShadingInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & colorBlendState,ImageBackingMode backingMode,const bool useFragmentShadingRate)2032 MinSampleShadingInstance::MinSampleShadingInstance(Context &context,
2033                                                    const PipelineConstructionType pipelineConstructionType,
2034                                                    VkPrimitiveTopology topology, float pointSize,
2035                                                    const std::vector<Vertex4RGBA> &vertices,
2036                                                    const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2037                                                    const VkPipelineColorBlendAttachmentState &colorBlendState,
2038                                                    ImageBackingMode backingMode, const bool useFragmentShadingRate)
2039     : vkt::TestInstance(context)
2040     , m_pipelineConstructionType(pipelineConstructionType)
2041     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2042     , m_renderSize(32, 32)
2043     , m_primitiveTopology(topology)
2044     , m_vertices(vertices)
2045     , m_multisampleStateParams(multisampleStateParams)
2046     , m_colorBlendState(colorBlendState)
2047     , m_backingMode(backingMode)
2048     , m_useFragmentShadingRate(useFragmentShadingRate)
2049 {
2050     DE_UNREF(pointSize);
2051 }
2052 
iterate(void)2053 tcu::TestStatus MinSampleShadingInstance::iterate(void)
2054 {
2055     de::MovePtr<tcu::TextureLevel> noSampleshadingImage;
2056     std::vector<tcu::TextureLevel> sampleShadedImages;
2057 
2058     // Render and resolve without sample shading
2059     {
2060         VkPipelineMultisampleStateCreateInfo multisampleStateParms = m_multisampleStateParams;
2061         multisampleStateParms.sampleShadingEnable                  = VK_FALSE;
2062         multisampleStateParms.minSampleShading                     = 0.0;
2063 
2064         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2065                                      m_primitiveTopology, m_vertices, multisampleStateParms, m_colorBlendState,
2066                                      RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2067         noSampleshadingImage = renderer.render();
2068     }
2069 
2070     // Render with test minSampleShading and collect per-sample images
2071     {
2072         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2073                                      m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState,
2074                                      RENDER_TYPE_COPY_SAMPLES, m_backingMode, m_useFragmentShadingRate);
2075         renderer.render();
2076 
2077         sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
2078         for (uint32_t sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
2079         {
2080             sampleShadedImages[sampleId] = *renderer.getSingleSampledImage(sampleId);
2081         }
2082     }
2083 
2084     // Log images
2085     {
2086         tcu::TestLog &testLog = m_context.getTestContext().getLog();
2087 
2088         testLog << tcu::TestLog::ImageSet("Images", "Images")
2089                 << tcu::TestLog::Image("noSampleshadingImage", "Image rendered without sample shading",
2090                                        noSampleshadingImage->getAccess());
2091 
2092         for (uint32_t sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
2093         {
2094             testLog << tcu::TestLog::Image("sampleShadedImage", "One sample of sample shaded image",
2095                                            sampleShadedImages[sampleId].getAccess());
2096         }
2097         testLog << tcu::TestLog::EndImageSet;
2098     }
2099 
2100     return verifySampleShadedImage(sampleShadedImages, noSampleshadingImage->getAccess());
2101 }
2102 
verifySampleShadedImage(const std::vector<tcu::TextureLevel> & sampleShadedImages,const tcu::ConstPixelBufferAccess & noSampleshadingImage)2103 tcu::TestStatus MinSampleShadingInstance::verifySampleShadedImage(
2104     const std::vector<tcu::TextureLevel> &sampleShadedImages, const tcu::ConstPixelBufferAccess &noSampleshadingImage)
2105 {
2106     const uint32_t pixelCount =
2107         noSampleshadingImage.getWidth() * noSampleshadingImage.getHeight() * noSampleshadingImage.getDepth();
2108 
2109     bool anyPixelCovered = false;
2110 
2111     for (uint32_t pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
2112     {
2113         const uint32_t noSampleShadingValue = *((const uint32_t *)noSampleshadingImage.getDataPtr() + pixelNdx);
2114 
2115         if (noSampleShadingValue == 0)
2116         {
2117             // non-covered pixel, continue
2118             continue;
2119         }
2120         else
2121         {
2122             anyPixelCovered = true;
2123         }
2124 
2125         int numNotCoveredSamples = 0;
2126 
2127         std::map<uint32_t, uint32_t> histogram; // map<pixel value, number of occurrences>
2128 
2129         // Collect histogram of occurrences or each pixel across all samples
2130         for (size_t i = 0; i < sampleShadedImages.size(); ++i)
2131         {
2132             const uint32_t sampleShadedValue =
2133                 *((const uint32_t *)sampleShadedImages[i].getAccess().getDataPtr() + pixelNdx);
2134 
2135             if (sampleShadedValue == 0)
2136             {
2137                 numNotCoveredSamples++;
2138                 continue;
2139             }
2140 
2141             if (histogram.find(sampleShadedValue) != histogram.end())
2142                 histogram[sampleShadedValue]++;
2143             else
2144                 histogram[sampleShadedValue] = 1;
2145         }
2146 
2147         if (numNotCoveredSamples == static_cast<int>(sampleShadedImages.size()))
2148         {
2149             return tcu::TestStatus::fail("Got uncovered pixel, where covered samples were expected");
2150         }
2151 
2152         const int uniqueColorsCount          = (int)histogram.size();
2153         const int expectedUniqueSamplesCount = static_cast<int>(
2154             m_multisampleStateParams.minSampleShading * static_cast<float>(sampleShadedImages.size()) + 0.5f);
2155 
2156         if (uniqueColorsCount + numNotCoveredSamples < expectedUniqueSamplesCount)
2157         {
2158             return tcu::TestStatus::fail("Got less unique colors than requested through minSampleShading");
2159         }
2160     }
2161 
2162     if (!anyPixelCovered)
2163     {
2164         return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShading");
2165     }
2166 
2167     return tcu::TestStatus::pass("Got proper count of unique colors");
2168 }
2169 
MinSampleShadingDisabledInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,ImageBackingMode backingMode,const bool useFragmentShadingRate)2170 MinSampleShadingDisabledInstance::MinSampleShadingDisabledInstance(
2171     Context &context, const PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology topology,
2172     float pointSize, const std::vector<Vertex4RGBA> &vertices,
2173     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2174     const VkPipelineColorBlendAttachmentState &blendState, ImageBackingMode backingMode,
2175     const bool useFragmentShadingRate)
2176     : MinSampleShadingInstance(context, pipelineConstructionType, topology, pointSize, vertices, multisampleStateParams,
2177                                blendState, backingMode, useFragmentShadingRate)
2178 {
2179 }
2180 
verifySampleShadedImage(const std::vector<tcu::TextureLevel> & sampleShadedImages,const tcu::ConstPixelBufferAccess & noSampleshadingImage)2181 tcu::TestStatus MinSampleShadingDisabledInstance::verifySampleShadedImage(
2182     const std::vector<tcu::TextureLevel> &sampleShadedImages, const tcu::ConstPixelBufferAccess &noSampleshadingImage)
2183 {
2184     const uint32_t samplesCount = (int)sampleShadedImages.size();
2185     const uint32_t width        = noSampleshadingImage.getWidth();
2186     const uint32_t height       = noSampleshadingImage.getHeight();
2187     const uint32_t depth        = noSampleshadingImage.getDepth();
2188     const tcu::UVec4 zeroPixel  = tcu::UVec4();
2189     bool anyPixelCovered        = false;
2190 
2191     DE_ASSERT(depth == 1);
2192     DE_UNREF(depth);
2193 
2194     for (uint32_t y = 0; y < height; ++y)
2195         for (uint32_t x = 0; x < width; ++x)
2196         {
2197             const tcu::UVec4 noSampleShadingValue = noSampleshadingImage.getPixelUint(x, y);
2198 
2199             if (noSampleShadingValue == zeroPixel)
2200                 continue;
2201 
2202             anyPixelCovered               = true;
2203             tcu::UVec4 sampleShadingValue = tcu::UVec4();
2204 
2205             // Collect histogram of occurrences or each pixel across all samples
2206             for (size_t i = 0; i < samplesCount; ++i)
2207             {
2208                 const tcu::UVec4 sampleShadedValue = sampleShadedImages[i].getAccess().getPixelUint(x, y);
2209 
2210                 sampleShadingValue += sampleShadedValue;
2211             }
2212 
2213             sampleShadingValue = sampleShadingValue / samplesCount;
2214 
2215             if (sampleShadingValue.w() != 255)
2216             {
2217                 return tcu::TestStatus::fail("Invalid Alpha channel value");
2218             }
2219 
2220             if (sampleShadingValue != noSampleShadingValue)
2221             {
2222                 return tcu::TestStatus::fail("Invalid color");
2223             }
2224         }
2225 
2226     if (!anyPixelCovered)
2227     {
2228         return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShadingDisabled");
2229     }
2230 
2231     return tcu::TestStatus::pass("Got proper count of unique colors");
2232 }
2233 
SampleMaskInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,float pointSize,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,ImageBackingMode backingMode,const bool useFragmentShadingRate)2234 SampleMaskInstance::SampleMaskInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
2235                                        VkPrimitiveTopology topology, float pointSize,
2236                                        const std::vector<Vertex4RGBA> &vertices,
2237                                        const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2238                                        const VkPipelineColorBlendAttachmentState &blendState,
2239                                        ImageBackingMode backingMode, const bool useFragmentShadingRate)
2240     : vkt::TestInstance(context)
2241     , m_pipelineConstructionType(pipelineConstructionType)
2242     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2243     , m_renderSize(32, 32)
2244     , m_primitiveTopology(topology)
2245     , m_vertices(vertices)
2246     , m_multisampleStateParams(multisampleStateParams)
2247     , m_colorBlendState(blendState)
2248     , m_backingMode(backingMode)
2249     , m_useFragmentShadingRate(useFragmentShadingRate)
2250 {
2251     DE_UNREF(pointSize);
2252 }
2253 
iterate(void)2254 tcu::TestStatus SampleMaskInstance::iterate(void)
2255 {
2256     de::MovePtr<tcu::TextureLevel> testSampleMaskImage;
2257     de::MovePtr<tcu::TextureLevel> minSampleMaskImage;
2258     de::MovePtr<tcu::TextureLevel> maxSampleMaskImage;
2259 
2260     // Render with test flags
2261     {
2262         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2263                                      m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState,
2264                                      RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2265         testSampleMaskImage = renderer.render();
2266     }
2267 
2268     // Render with all flags off
2269     {
2270         VkPipelineMultisampleStateCreateInfo multisampleParams = m_multisampleStateParams;
2271         const std::vector<VkSampleMask> sampleMask(multisampleParams.rasterizationSamples / 32, (VkSampleMask)0);
2272 
2273         multisampleParams.pSampleMask = sampleMask.data();
2274 
2275         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2276                                      m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState,
2277                                      RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2278         minSampleMaskImage = renderer.render();
2279     }
2280 
2281     // Render with all flags on
2282     {
2283         VkPipelineMultisampleStateCreateInfo multisampleParams = m_multisampleStateParams;
2284         const std::vector<VkSampleMask> sampleMask(multisampleParams.rasterizationSamples / 32, ~((VkSampleMask)0));
2285 
2286         multisampleParams.pSampleMask = sampleMask.data();
2287 
2288         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2289                                      m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState,
2290                                      RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2291         maxSampleMaskImage = renderer.render();
2292     }
2293 
2294     return verifyImage(testSampleMaskImage->getAccess(), minSampleMaskImage->getAccess(),
2295                        maxSampleMaskImage->getAccess());
2296 }
2297 
verifyImage(const tcu::ConstPixelBufferAccess & testSampleMaskImage,const tcu::ConstPixelBufferAccess & minSampleMaskImage,const tcu::ConstPixelBufferAccess & maxSampleMaskImage)2298 tcu::TestStatus SampleMaskInstance::verifyImage(const tcu::ConstPixelBufferAccess &testSampleMaskImage,
2299                                                 const tcu::ConstPixelBufferAccess &minSampleMaskImage,
2300                                                 const tcu::ConstPixelBufferAccess &maxSampleMaskImage)
2301 {
2302     const uint32_t testColorCount = getUniqueColorsCount(testSampleMaskImage);
2303     const uint32_t minColorCount  = getUniqueColorsCount(minSampleMaskImage);
2304     const uint32_t maxColorCount  = getUniqueColorsCount(maxSampleMaskImage);
2305 
2306     tcu::TestLog &log = m_context.getTestContext().getLog();
2307 
2308     log << tcu::TestLog::Message << "\nColors found: " << testColorCount << "\n"
2309         << "Min. colors expected: " << minColorCount << "\n"
2310         << "Max. colors expected: " << maxColorCount << "\n"
2311         << tcu::TestLog::EndMessage;
2312 
2313     if (minColorCount > testColorCount || testColorCount > maxColorCount)
2314         return tcu::TestStatus::fail("Unique colors out of expected bounds");
2315     else
2316         return tcu::TestStatus::pass("Unique colors within expected bounds");
2317 }
2318 #ifndef CTS_USES_VULKANSC
testRasterSamplesConsistency(Context & context,MultisampleTestParams params)2319 tcu::TestStatus testRasterSamplesConsistency(Context &context, MultisampleTestParams params)
2320 {
2321     const VkSampleCountFlagBits samples[] = {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT,  VK_SAMPLE_COUNT_4_BIT,
2322                                              VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_32_BIT,
2323                                              VK_SAMPLE_COUNT_64_BIT};
2324 
2325     const Vertex4RGBA vertexData[3] = {{tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
2326                                        {tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)},
2327                                        {tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)}};
2328 
2329     const std::vector<Vertex4RGBA> vertices(vertexData, vertexData + 3);
2330     uint32_t prevUniqueColors = 2;
2331     int renderCount           = 0;
2332 
2333     // Do not render with 1 sample (start with samplesNdx = 1).
2334     for (int samplesNdx = 1; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2335     {
2336         if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), samples[samplesNdx]))
2337             continue;
2338 
2339         if (params.useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, samples[samplesNdx]))
2340             continue;
2341 
2342         const VkPipelineMultisampleStateCreateInfo multisampleStateParams{
2343             VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2344             DE_NULL,                                                  // const void* pNext;
2345             0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
2346             samples[samplesNdx],                                      // VkSampleCountFlagBits rasterizationSamples;
2347             false,                                                    // VkBool32 sampleShadingEnable;
2348             0.0f,                                                     // float minSampleShading;
2349             DE_NULL,                                                  // const VkSampleMask* pSampleMask;
2350             false,                                                    // VkBool32 alphaToCoverageEnable;
2351             false                                                     // VkBool32 alphaToOneEnable;
2352         };
2353 
2354         MultisampleRenderer renderer(context, params.pipelineConstructionType, VK_FORMAT_R8G8B8A8_UNORM,
2355                                      tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices,
2356                                      multisampleStateParams, getDefaultColorBlendAttachmentState(), RENDER_TYPE_RESOLVE,
2357                                      params.backingMode, params.useFragmentShadingRate);
2358         de::MovePtr<tcu::TextureLevel> result = renderer.render();
2359         const uint32_t uniqueColors           = getUniqueColorsCount(result->getAccess());
2360 
2361         renderCount++;
2362 
2363         if (prevUniqueColors > uniqueColors)
2364         {
2365             std::ostringstream message;
2366 
2367             message << "More unique colors generated with " << samples[samplesNdx - 1] << " than with "
2368                     << samples[samplesNdx];
2369             return tcu::TestStatus::fail(message.str());
2370         }
2371 
2372         prevUniqueColors = uniqueColors;
2373     }
2374 
2375     if (renderCount == 0)
2376     {
2377         if (params.useFragmentShadingRate && !context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
2378             TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate is unsupported");
2379         TCU_THROW(NotSupportedError, "Multisampling is unsupported");
2380     }
2381 
2382     return tcu::TestStatus::pass("Number of unique colors increases as the sample count increases");
2383 }
2384 #endif // CTS_USES_VULKANSC
2385 
2386 // AlphaToOneInstance
2387 
AlphaToOneInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,ImageBackingMode backingMode,const bool useFragmentShadingRate)2388 AlphaToOneInstance::AlphaToOneInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
2389                                        VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
2390                                        const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2391                                        const VkPipelineColorBlendAttachmentState &blendState,
2392                                        ImageBackingMode backingMode, const bool useFragmentShadingRate)
2393     : vkt::TestInstance(context)
2394     , m_pipelineConstructionType(pipelineConstructionType)
2395     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2396     , m_renderSize(32, 32)
2397     , m_primitiveTopology(topology)
2398     , m_vertices(vertices)
2399     , m_multisampleStateParams(multisampleStateParams)
2400     , m_colorBlendState(blendState)
2401     , m_backingMode(backingMode)
2402     , m_useFragmentShadingRate(useFragmentShadingRate)
2403 {
2404 }
2405 
iterate(void)2406 tcu::TestStatus AlphaToOneInstance::iterate(void)
2407 {
2408     DE_ASSERT(m_multisampleStateParams.alphaToOneEnable);
2409     DE_ASSERT(m_colorBlendState.blendEnable);
2410 
2411     de::MovePtr<tcu::TextureLevel> alphaOneImage;
2412     de::MovePtr<tcu::TextureLevel> noAlphaOneImage;
2413 
2414     RenderType renderType = m_multisampleStateParams.rasterizationSamples == vk::VK_SAMPLE_COUNT_1_BIT ?
2415                                 RENDER_TYPE_SINGLE_SAMPLE :
2416                                 RENDER_TYPE_RESOLVE;
2417 
2418     // Render with blend enabled and alpha to one on
2419     {
2420         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2421                                      m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState,
2422                                      renderType, m_backingMode, m_useFragmentShadingRate);
2423         alphaOneImage = renderer.render();
2424     }
2425 
2426     // Render with blend enabled and alpha to one off
2427     {
2428         VkPipelineMultisampleStateCreateInfo multisampleParams = m_multisampleStateParams;
2429         multisampleParams.alphaToOneEnable                     = false;
2430 
2431         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2432                                      m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, renderType,
2433                                      m_backingMode, m_useFragmentShadingRate);
2434         noAlphaOneImage = renderer.render();
2435     }
2436 
2437     return verifyImage(alphaOneImage->getAccess(), noAlphaOneImage->getAccess());
2438 }
2439 
verifyImage(const tcu::ConstPixelBufferAccess & alphaOneImage,const tcu::ConstPixelBufferAccess & noAlphaOneImage)2440 tcu::TestStatus AlphaToOneInstance::verifyImage(const tcu::ConstPixelBufferAccess &alphaOneImage,
2441                                                 const tcu::ConstPixelBufferAccess &noAlphaOneImage)
2442 {
2443     for (int y = 0; y < m_renderSize.y(); y++)
2444     {
2445         for (int x = 0; x < m_renderSize.x(); x++)
2446         {
2447             if (alphaOneImage.getPixel(x, y).w() != 1.0)
2448             {
2449                 std::ostringstream message;
2450                 message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y) << " doesn't have alpha set to 1";
2451                 return tcu::TestStatus::fail(message.str());
2452             }
2453 
2454             if (!tcu::boolAll(tcu::greaterThanEqual(alphaOneImage.getPixel(x, y), noAlphaOneImage.getPixel(x, y))))
2455             {
2456                 std::ostringstream message;
2457                 message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y)
2458                         << " >= " << noAlphaOneImage.getPixel(x, y);
2459                 return tcu::TestStatus::fail(message.str());
2460             }
2461         }
2462     }
2463 
2464     return tcu::TestStatus::pass(
2465         "Image rendered with alpha-to-one contains pixels of image rendered with no alpha-to-one");
2466 }
2467 
2468 // AlphaToCoverageInstance
2469 
AlphaToCoverageInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,GeometryType geometryType,ImageBackingMode backingMode,const bool useFragmentShadingRate,const bool checkDepthBuffer)2470 AlphaToCoverageInstance::AlphaToCoverageInstance(Context &context,
2471                                                  const PipelineConstructionType pipelineConstructionType,
2472                                                  VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
2473                                                  const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2474                                                  const VkPipelineColorBlendAttachmentState &blendState,
2475                                                  GeometryType geometryType, ImageBackingMode backingMode,
2476                                                  const bool useFragmentShadingRate, const bool checkDepthBuffer)
2477     : vkt::TestInstance(context)
2478     , m_pipelineConstructionType(pipelineConstructionType)
2479     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2480     , m_depthStencilFormat(VK_FORMAT_D16_UNORM)
2481     , m_renderSize(32, 32)
2482     , m_primitiveTopology(topology)
2483     , m_vertices(vertices)
2484     , m_multisampleStateParams(multisampleStateParams)
2485     , m_colorBlendState(blendState)
2486     , m_geometryType(geometryType)
2487     , m_backingMode(backingMode)
2488     , m_useFragmentShadingRate(useFragmentShadingRate)
2489     , m_checkDepthBuffer(checkDepthBuffer)
2490 {
2491 }
2492 
iterate(void)2493 tcu::TestStatus AlphaToCoverageInstance::iterate(void)
2494 {
2495     DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
2496 
2497     de::MovePtr<tcu::TextureLevel> result;
2498     MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat,
2499                                  m_renderSize, m_checkDepthBuffer, false, 1u, &m_primitiveTopology, &m_vertices,
2500                                  m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode,
2501                                  m_useFragmentShadingRate);
2502 
2503     result = renderer.render();
2504 
2505     const auto colorStatus = verifyImage(result->getAccess());
2506     auto depthStatus       = tcu::TestStatus::pass("Pass");
2507 
2508     if (m_checkDepthBuffer)
2509     {
2510         const auto redrawResult = renderer.renderReusingDepth();
2511         depthStatus             = verifyDepthBufferCheck(redrawResult->getAccess());
2512     }
2513 
2514     if (colorStatus.getCode() == QP_TEST_RESULT_FAIL)
2515         return colorStatus;
2516 
2517     if (depthStatus.getCode() == QP_TEST_RESULT_FAIL)
2518         return depthStatus;
2519 
2520     return colorStatus;
2521 }
2522 
verifyDepthBufferCheck(const tcu::ConstPixelBufferAccess & result)2523 tcu::TestStatus AlphaToCoverageInstance::verifyDepthBufferCheck(const tcu::ConstPixelBufferAccess &result)
2524 {
2525     const tcu::Vec4 refColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match "checkDepth-vert".
2526     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f);
2527 
2528     if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "BlueColor", "", refColor, result, threshold,
2529                                     tcu::COMPARE_LOG_ON_ERROR))
2530         return tcu::TestStatus::fail("Depth buffer verification failed: depth buffer was not clear");
2531     return tcu::TestStatus::pass("Pass");
2532 }
2533 
verifyImage(const tcu::ConstPixelBufferAccess & result)2534 tcu::TestStatus AlphaToCoverageInstance::verifyImage(const tcu::ConstPixelBufferAccess &result)
2535 {
2536     float maxColorValue;
2537     float minColorValue;
2538 
2539     switch (m_geometryType)
2540     {
2541     case GEOMETRY_TYPE_OPAQUE_QUAD:
2542         maxColorValue = 1.01f;
2543         minColorValue = 0.99f;
2544         break;
2545 
2546     case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
2547         maxColorValue = 0.52f;
2548         minColorValue = 0.0f;
2549         break;
2550 
2551     case GEOMETRY_TYPE_INVISIBLE_QUAD:
2552         maxColorValue = 0.01f;
2553         minColorValue = 0.0f;
2554         break;
2555 
2556     default:
2557         maxColorValue = 0.0f;
2558         minColorValue = 0.0f;
2559         DE_ASSERT(false);
2560     }
2561 
2562     auto &log = m_context.getTestContext().getLog();
2563     log << tcu::TestLog::Image("Result", "Result Image", result);
2564 
2565     for (int y = 0; y < m_renderSize.y(); y++)
2566     {
2567         for (int x = 0; x < m_renderSize.x(); x++)
2568         {
2569             const auto pixel = result.getPixel(x, y);
2570             const auto red   = pixel.x();
2571 
2572             if (red > maxColorValue || red < minColorValue)
2573             {
2574                 std::ostringstream message;
2575                 message << "Pixel is not in the expected range: " << red << " not in [" << minColorValue << ", "
2576                         << maxColorValue << "]";
2577                 return tcu::TestStatus::fail(message.str());
2578             }
2579         }
2580     }
2581 
2582     return tcu::TestStatus::pass("Image matches reference value");
2583 }
2584 
2585 // AlphaToCoverageNoColorAttachmentInstance
2586 
AlphaToCoverageNoColorAttachmentInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,GeometryType geometryType,ImageBackingMode backingMode,const bool useFragmentShadingRate)2587 AlphaToCoverageNoColorAttachmentInstance::AlphaToCoverageNoColorAttachmentInstance(
2588     Context &context, const PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology topology,
2589     const std::vector<Vertex4RGBA> &vertices, const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2590     const VkPipelineColorBlendAttachmentState &blendState, GeometryType geometryType, ImageBackingMode backingMode,
2591     const bool useFragmentShadingRate)
2592     : vkt::TestInstance(context)
2593     , m_pipelineConstructionType(pipelineConstructionType)
2594     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2595     , m_depthStencilFormat(VK_FORMAT_D16_UNORM)
2596     , m_renderSize(32, 32)
2597     , m_primitiveTopology(topology)
2598     , m_vertices(vertices)
2599     , m_multisampleStateParams(multisampleStateParams)
2600     , m_colorBlendState(blendState)
2601     , m_geometryType(geometryType)
2602     , m_backingMode(backingMode)
2603     , m_useFragmentShadingRate(useFragmentShadingRate)
2604 {
2605 }
2606 
iterate(void)2607 tcu::TestStatus AlphaToCoverageNoColorAttachmentInstance::iterate(void)
2608 {
2609     DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
2610 
2611     de::MovePtr<tcu::TextureLevel> result;
2612     MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat,
2613                                  m_renderSize, true, false, 1u, &m_primitiveTopology, &m_vertices,
2614                                  m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_DEPTHSTENCIL_ONLY,
2615                                  m_backingMode, m_useFragmentShadingRate, 1.0f);
2616 
2617     result = renderer.render();
2618 
2619     return verifyImage(result->getAccess());
2620 }
2621 
verifyImage(const tcu::ConstPixelBufferAccess & result)2622 tcu::TestStatus AlphaToCoverageNoColorAttachmentInstance::verifyImage(const tcu::ConstPixelBufferAccess &result)
2623 {
2624     for (int y = 0; y < m_renderSize.y(); y++)
2625     {
2626         for (int x = 0; x < m_renderSize.x(); x++)
2627         {
2628             // Expect full red for each pixel. Fail if clear color is showing.
2629             if (result.getPixel(x, y).x() < 1.0f)
2630             {
2631                 // Log result image when failing.
2632                 m_context.getTestContext().getLog()
2633                     << tcu::TestLog::ImageSet("Result", "Result image")
2634                     << tcu::TestLog::Image("Rendered", "Rendered image", result) << tcu::TestLog::EndImageSet;
2635 
2636                 return tcu::TestStatus::fail("Fail");
2637             }
2638         }
2639     }
2640 
2641     return tcu::TestStatus::pass("Pass");
2642 }
2643 
2644 // AlphaToCoverageColorUnusedAttachmentInstance
2645 
AlphaToCoverageColorUnusedAttachmentInstance(Context & context,const PipelineConstructionType pipelineConstructionType,VkPrimitiveTopology topology,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,GeometryType geometryType,ImageBackingMode backingMode,const bool useFragmentShadingRate)2646 AlphaToCoverageColorUnusedAttachmentInstance::AlphaToCoverageColorUnusedAttachmentInstance(
2647     Context &context, const PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology topology,
2648     const std::vector<Vertex4RGBA> &vertices, const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
2649     const VkPipelineColorBlendAttachmentState &blendState, GeometryType geometryType, ImageBackingMode backingMode,
2650     const bool useFragmentShadingRate)
2651     : vkt::TestInstance(context)
2652     , m_pipelineConstructionType(pipelineConstructionType)
2653     , m_colorFormat(VK_FORMAT_R5G6B5_UNORM_PACK16)
2654     , m_renderSize(32, 32)
2655     , m_primitiveTopology(topology)
2656     , m_vertices(vertices)
2657     , m_multisampleStateParams(multisampleStateParams)
2658     , m_colorBlendState(blendState)
2659     , m_geometryType(geometryType)
2660     , m_backingMode(backingMode)
2661     , m_useFragmentShadingRate(useFragmentShadingRate)
2662 {
2663 }
2664 
iterate(void)2665 tcu::TestStatus AlphaToCoverageColorUnusedAttachmentInstance::iterate(void)
2666 {
2667     DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
2668 
2669     de::MovePtr<tcu::TextureLevel> result;
2670     MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2671                                  m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState,
2672                                  RENDER_TYPE_UNUSED_ATTACHMENT, m_backingMode, m_useFragmentShadingRate);
2673 
2674     result = renderer.render();
2675 
2676     return verifyImage(result->getAccess());
2677 }
2678 
verifyImage(const tcu::ConstPixelBufferAccess & result)2679 tcu::TestStatus AlphaToCoverageColorUnusedAttachmentInstance::verifyImage(const tcu::ConstPixelBufferAccess &result)
2680 {
2681     for (int y = 0; y < m_renderSize.y(); y++)
2682     {
2683         for (int x = 0; x < m_renderSize.x(); x++)
2684         {
2685             // Quad color gets written to color buffer at location 1, and the alpha value to location 0 which is unused.
2686             // The coverage should still be affected by the alpha written to location 0.
2687             if ((m_geometryType == GEOMETRY_TYPE_OPAQUE_QUAD && result.getPixel(x, y).x() < 1.0f) ||
2688                 (m_geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD && result.getPixel(x, y).x() > 0.0f))
2689             {
2690                 // Log result image when failing.
2691                 m_context.getTestContext().getLog()
2692                     << tcu::TestLog::ImageSet("Result", "Result image")
2693                     << tcu::TestLog::Image("Rendered", "Rendered image", result) << tcu::TestLog::EndImageSet;
2694 
2695                 return tcu::TestStatus::fail("Fail");
2696             }
2697         }
2698     }
2699 
2700     return tcu::TestStatus::pass("Pass");
2701 }
2702 
2703 // SampleMaskWithConservativeInstance
2704 
SampleMaskWithConservativeInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const VkSampleCountFlagBits rasterizationSamples,const bool enableMinSampleShading,const float minSampleShading,const bool enableSampleMask,const VkSampleMask sampleMask,const VkConservativeRasterizationModeEXT conservativeRasterizationMode,const bool enablePostDepthCoverage,const bool enableFullyCoveredEXT,const RenderType renderType,const bool useFragmentShadingRate)2705 SampleMaskWithConservativeInstance::SampleMaskWithConservativeInstance(
2706     Context &context, const PipelineConstructionType pipelineConstructionType,
2707     const VkSampleCountFlagBits rasterizationSamples, const bool enableMinSampleShading, const float minSampleShading,
2708     const bool enableSampleMask, const VkSampleMask sampleMask,
2709     const VkConservativeRasterizationModeEXT conservativeRasterizationMode, const bool enablePostDepthCoverage,
2710     const bool enableFullyCoveredEXT, const RenderType renderType, const bool useFragmentShadingRate)
2711     : vkt::TestInstance(context)
2712     , m_pipelineConstructionType(pipelineConstructionType)
2713     , m_rasterizationSamples(rasterizationSamples)
2714     , m_enablePostDepthCoverage(enablePostDepthCoverage)
2715     , m_enableFullyCoveredEXT(enableFullyCoveredEXT)
2716     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2717     , m_depthStencilFormat(VK_FORMAT_D16_UNORM)
2718     , m_renderSize(tcu::IVec2(10, 10))
2719     , m_useDepth(true)
2720     , m_useStencil(false)
2721     , m_useConservative(true)
2722     , m_useFragmentShadingRate(useFragmentShadingRate)
2723     , m_conservativeRasterizationMode(conservativeRasterizationMode)
2724     , m_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2725     , m_renderColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
2726     , m_depthClearValue(0.5f)
2727     , m_vertices(generateVertices())
2728     , m_enableSampleMask(enableSampleMask)
2729     , m_sampleMask(std::vector<VkSampleMask>{sampleMask})
2730     , m_enableMinSampleShading(enableMinSampleShading)
2731     , m_minSampleShading(minSampleShading)
2732     , m_multisampleStateParams(
2733           getMultisampleState(rasterizationSamples, enableMinSampleShading, minSampleShading, enableSampleMask))
2734     , m_rasterizationConservativeStateCreateInfo(
2735           getRasterizationConservativeStateCreateInfo(conservativeRasterizationMode))
2736     , m_blendState(getDefaultColorBlendAttachmentState())
2737     , m_renderType(renderType)
2738     , m_imageBackingMode(IMAGE_BACKING_MODE_REGULAR)
2739 {
2740 }
2741 
iterate(void)2742 tcu::TestStatus SampleMaskWithConservativeInstance::iterate(void)
2743 {
2744 
2745     de::MovePtr<tcu::TextureLevel> noSampleshadingImage;
2746     std::vector<tcu::TextureLevel> sampleShadedImages;
2747 
2748     {
2749         MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat,
2750                                      m_renderSize, m_useDepth, m_useStencil, m_useConservative,
2751                                      m_useFragmentShadingRate, 1u, &m_topology, &m_vertices, m_multisampleStateParams,
2752                                      m_blendState, m_rasterizationConservativeStateCreateInfo, RENDER_TYPE_RESOLVE,
2753                                      m_imageBackingMode, m_depthClearValue);
2754         noSampleshadingImage = renderer.render();
2755     }
2756 
2757     {
2758         const VkPipelineColorBlendAttachmentState colorBlendState = {
2759             false,                                                // VkBool32 blendEnable;
2760             VK_BLEND_FACTOR_ONE,                                  // VkBlendFactor srcColorBlendFactor;
2761             VK_BLEND_FACTOR_ZERO,                                 // VkBlendFactor dstColorBlendFactor;
2762             VK_BLEND_OP_ADD,                                      // VkBlendOp colorBlendOp;
2763             VK_BLEND_FACTOR_ONE,                                  // VkBlendFactor srcAlphaBlendFactor;
2764             VK_BLEND_FACTOR_ZERO,                                 // VkBlendFactor dstAlphaBlendFactor;
2765             VK_BLEND_OP_ADD,                                      // VkBlendOp alphaBlendOp;
2766             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
2767                 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
2768 
2769         MultisampleRenderer mRenderer(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize,
2770                                       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, m_vertices, m_multisampleStateParams,
2771                                       colorBlendState, RENDER_TYPE_COPY_SAMPLES, IMAGE_BACKING_MODE_REGULAR,
2772                                       m_useFragmentShadingRate);
2773         mRenderer.render();
2774 
2775         sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
2776         for (uint32_t sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
2777         {
2778             sampleShadedImages[sampleId] = *mRenderer.getSingleSampledImage(sampleId);
2779         }
2780     }
2781 
2782     return verifyImage(sampleShadedImages, noSampleshadingImage->getAccess());
2783 }
2784 
getMultisampleState(const VkSampleCountFlagBits rasterizationSamples,const bool enableMinSampleShading,const float minSampleShading,const bool enableSampleMask)2785 VkPipelineMultisampleStateCreateInfo SampleMaskWithConservativeInstance::getMultisampleState(
2786     const VkSampleCountFlagBits rasterizationSamples, const bool enableMinSampleShading, const float minSampleShading,
2787     const bool enableSampleMask)
2788 {
2789     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
2790         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2791         DE_NULL,                                                  // const void* pNext;
2792         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
2793         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
2794         enableMinSampleShading ? VK_TRUE : VK_FALSE,              // VkBool32 sampleShadingEnable;
2795         enableMinSampleShading ? minSampleShading : 0.0f,         // float minSampleShading;
2796         enableSampleMask ? m_sampleMask.data() : DE_NULL,         // const VkSampleMask* pSampleMask;
2797         false,                                                    // VkBool32 alphaToCoverageEnable;
2798         false                                                     // VkBool32 alphaToOneEnable;
2799     };
2800 
2801     return multisampleStateParams;
2802 }
2803 
2804 VkPipelineRasterizationConservativeStateCreateInfoEXT SampleMaskWithConservativeInstance::
getRasterizationConservativeStateCreateInfo(const VkConservativeRasterizationModeEXT conservativeRasterizationMode)2805     getRasterizationConservativeStateCreateInfo(const VkConservativeRasterizationModeEXT conservativeRasterizationMode)
2806 {
2807     const VkPipelineRasterizationConservativeStateCreateInfoEXT rasterizationConservativeStateCreateInfo = {
2808         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT, //  VkStructureType sType;
2809         DE_NULL,                                                                     //  const void* pNext;
2810         (VkPipelineRasterizationConservativeStateCreateFlagsEXT)0, //  VkPipelineRasterizationConservativeStateCreateFlagsEXT flags;
2811         conservativeRasterizationMode, //  VkConservativeRasterizationModeEXT conservativeRasterizationMode;
2812         0.0f                           //  float extraPrimitiveOverestimationSize;
2813     };
2814 
2815     return rasterizationConservativeStateCreateInfo;
2816 }
2817 
generateVertices(void)2818 std::vector<Vertex4RGBA> SampleMaskWithConservativeInstance::generateVertices(void)
2819 {
2820     std::vector<Vertex4RGBA> vertices;
2821 
2822     {
2823         const Vertex4RGBA vertexInput = {tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), m_renderColor};
2824         vertices.push_back(vertexInput);
2825     }
2826     {
2827         const Vertex4RGBA vertexInput = {tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), m_renderColor};
2828         vertices.push_back(vertexInput);
2829     }
2830     {
2831         const Vertex4RGBA vertexInput = {tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), m_renderColor};
2832         vertices.push_back(vertexInput);
2833     }
2834 
2835     return vertices;
2836 }
2837 
verifyImage(const std::vector<tcu::TextureLevel> & sampleShadedImages,const tcu::ConstPixelBufferAccess & result)2838 tcu::TestStatus SampleMaskWithConservativeInstance::verifyImage(
2839     const std::vector<tcu::TextureLevel> &sampleShadedImages, const tcu::ConstPixelBufferAccess &result)
2840 {
2841     bool pass         = true;
2842     const int width   = result.getWidth();
2843     const int height  = result.getHeight();
2844     tcu::TestLog &log = m_context.getTestContext().getLog();
2845 
2846     const uint32_t samplesCount = (int)sampleShadedImages.size();
2847 
2848     for (size_t i = 0; i < samplesCount; ++i)
2849     {
2850         const tcu::ConstPixelBufferAccess &s = sampleShadedImages[i].getAccess();
2851 
2852         log << tcu::TestLog::ImageSet("Per sample image", "Per sampe image") << tcu::TestLog::Image("Layer", "Layer", s)
2853             << tcu::TestLog::EndImageSet;
2854     }
2855 
2856     // Leave sample count intact (return 1) if multiplication by minSampleShading won't exceed base 2
2857     // otherwise round up to the nearest power of 2
2858     auto sampleCountDivider = [](float x)
2859     {
2860         float power = 1.0;
2861         while (power < x)
2862         {
2863             power *= 2;
2864         }
2865         return power;
2866     };
2867 
2868     DE_ASSERT(width == 10);
2869     DE_ASSERT(height == 10);
2870 
2871     const tcu::Vec4 clearColor = tcu::Vec4(0.0f);
2872     std::vector<std::pair<int, int>> fullyCoveredPixelsCoordinateSet;
2873 
2874     // Generating set of pixel coordinate values covered by the triangle
2875     if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT)
2876     {
2877         for (int i = 0; i < width; i++)
2878         {
2879             for (int j = 0; j < height; j++)
2880             {
2881                 // Rasterization will cover half of the triangle plus 1 pixel edge due to the overeestimation
2882                 if (i < 5 && i + j < 11)
2883                     fullyCoveredPixelsCoordinateSet.push_back(std::make_pair(i, j));
2884             }
2885         }
2886     }
2887     else
2888     {
2889         if (m_useFragmentShadingRate && !m_enableMinSampleShading)
2890         {
2891             // When m_enableMinSampleShading is not enabled shader uses gl_FragFullyCoveredNV.
2892             // Additionaly when FSR coverage is enabled the tests uses a pipeline FSR rate of { 2,2 }
2893             // and as a result rasterization will cover only four pixels due to the underestimation.
2894             for (int i = 2; i < 4; i++)
2895                 for (int j = 2; j < 4; j++)
2896                     fullyCoveredPixelsCoordinateSet.push_back(std::make_pair(i, j));
2897         }
2898         else
2899         {
2900             for (int i = 1; i < width; i++)
2901             {
2902                 for (int j = 1; j < height; j++)
2903                 {
2904                     // Rasterization will cover half of the triangle minus 1 pixel edge due to the underestimation
2905                     if (i < 5 && i + j < 8)
2906                         fullyCoveredPixelsCoordinateSet.push_back(std::make_pair(i, j));
2907                 }
2908             }
2909         }
2910     }
2911 
2912     for (int x = 0; x < width; ++x)
2913         for (int y = 0; y < height; ++y)
2914         {
2915             const tcu::Vec4 resultPixel = result.getPixel(x, y);
2916 
2917             if (std::find(fullyCoveredPixelsCoordinateSet.begin(), fullyCoveredPixelsCoordinateSet.end(),
2918                           std::make_pair(x, y)) != fullyCoveredPixelsCoordinateSet.end())
2919             {
2920                 if (m_enableMinSampleShading)
2921                 {
2922                     tcu::UVec4 sampleShadingValue = tcu::UVec4();
2923                     for (size_t i = 0; i < samplesCount; ++i)
2924                     {
2925                         const tcu::UVec4 sampleShadedValue = sampleShadedImages[i].getAccess().getPixelUint(x, y);
2926 
2927                         sampleShadingValue += sampleShadedValue;
2928                     }
2929 
2930                     //Calculate coverage of a single sample Image based on accumulated value from the whole set
2931                     int sampleCoverageValue = sampleShadingValue.w() / samplesCount;
2932                     //Calculates an estimated coverage value based on the number of samples and the minimumSampleShading
2933                     int expectedCovergaveValue =
2934                         (int)(255.0 / sampleCountDivider((float)m_rasterizationSamples * m_minSampleShading)) + 1;
2935 
2936                     //The specification allows for larger sample count than minimum value, however resulted coverage should never be lower than minimum
2937                     if (sampleCoverageValue > expectedCovergaveValue)
2938                     {
2939                         log << tcu::TestLog::Message << "Coverage value " << sampleCoverageValue
2940                             << " greather than expected: " << expectedCovergaveValue << tcu::TestLog::EndMessage;
2941 
2942                         pass = false;
2943                     }
2944                 }
2945                 else if (m_enableSampleMask)
2946                 {
2947                     // Sample mask with all bits on will not affect fragment coverage
2948                     if (m_sampleMask[0] == 0xFFFFFFFF)
2949                     {
2950                         if (resultPixel != m_renderColor)
2951                         {
2952                             log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
2953                                 << " Reference: " << m_renderColor << tcu::TestLog::EndMessage;
2954 
2955                             pass = false;
2956                         }
2957                     }
2958                     // Sample mask with half bits off will reduce sample coverage by half
2959                     else if (m_sampleMask[0] == 0xAAAAAAAA)
2960                     {
2961 
2962                         const tcu::Vec4 renderColorHalfOpacity(0.0f, 0.5f, 0.0f, 0.5f);
2963                         const float threshold = 0.02f;
2964 
2965                         for (uint32_t componentNdx = 0u; componentNdx < m_renderColor.SIZE; ++componentNdx)
2966                         {
2967                             if ((renderColorHalfOpacity[componentNdx] != 0.0f &&
2968                                  resultPixel[componentNdx] <= (renderColorHalfOpacity[componentNdx] - threshold)) ||
2969                                 resultPixel[componentNdx] >= (renderColorHalfOpacity[componentNdx] + threshold))
2970                             {
2971                                 log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
2972                                     << " Reference: " << renderColorHalfOpacity << " +/- " << threshold
2973                                     << tcu::TestLog::EndMessage;
2974 
2975                                 pass = false;
2976                             }
2977                         }
2978                     }
2979                     // Sample mask with all bits off will cause all fragment to failed opacity test
2980                     else if (m_sampleMask[0] == 0x00000000)
2981                     {
2982                         if (resultPixel != clearColor)
2983                         {
2984                             log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
2985                                 << " Reference: " << clearColor << tcu::TestLog::EndMessage;
2986 
2987                             pass = false;
2988                         }
2989                     }
2990                     else
2991                     {
2992                         log << tcu::TestLog::Message << "Unexpected sample mask value" << tcu::TestLog::EndMessage;
2993 
2994                         pass = false;
2995                     }
2996                 }
2997                 else
2998                 {
2999                     if (resultPixel != m_renderColor)
3000                     {
3001                         log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3002                             << " Reference: " << m_renderColor << tcu::TestLog::EndMessage;
3003 
3004                         pass = false;
3005                     }
3006                 }
3007             }
3008             else
3009             {
3010                 if (resultPixel != clearColor)
3011                 {
3012                     log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3013                         << " Reference: " << clearColor << tcu::TestLog::EndMessage;
3014 
3015                     pass = false;
3016                 }
3017             }
3018         }
3019 
3020     if (pass)
3021         return tcu::TestStatus::pass("Passed");
3022     else
3023     {
3024         log << tcu::TestLog::ImageSet("LayerContent", "Layer content") << tcu::TestLog::Image("Layer", "Layer", result)
3025             << tcu::TestLog::EndImageSet;
3026 
3027         return tcu::TestStatus::fail("Failed");
3028     }
3029 }
3030 
3031 // SampleMaskWithDepthTestInstance
3032 #ifndef CTS_USES_VULKANSC
SampleMaskWithDepthTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const VkSampleCountFlagBits rasterizationSamples,const bool enablePostDepthCoverage,const bool useFragmentShadingRate)3033 SampleMaskWithDepthTestInstance::SampleMaskWithDepthTestInstance(
3034     Context &context, const PipelineConstructionType pipelineConstructionType,
3035     const VkSampleCountFlagBits rasterizationSamples, const bool enablePostDepthCoverage,
3036     const bool useFragmentShadingRate)
3037     : vkt::TestInstance(context)
3038     , m_pipelineConstructionType(pipelineConstructionType)
3039     , m_rasterizationSamples(rasterizationSamples)
3040     , m_enablePostDepthCoverage(enablePostDepthCoverage)
3041     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
3042     , m_depthStencilFormat(VK_FORMAT_D16_UNORM)
3043     , m_renderSize(tcu::IVec2(3, 3))
3044     , m_useDepth(true)
3045     , m_useStencil(false)
3046     , m_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
3047     , m_renderColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
3048     , m_vertices(generateVertices())
3049     , m_multisampleStateParams(getMultisampleState(rasterizationSamples))
3050     , m_blendState(getDefaultColorBlendAttachmentState())
3051     , m_renderType(RENDER_TYPE_RESOLVE)
3052     , m_imageBackingMode(IMAGE_BACKING_MODE_REGULAR)
3053     , m_depthClearValue(0.667f)
3054     , m_useFragmentShadingRate(useFragmentShadingRate)
3055 {
3056     m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_2_BIT] =
3057         SampleCoverage(1u, 1u); // !< Sample coverage of the diagonally halved pixel,
3058     m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_4_BIT] =
3059         SampleCoverage(2u, 2u); // !< with max possible subPixelPrecisionBits threshold
3060     m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_8_BIT]  = SampleCoverage(2u, 6u);  // !<
3061     m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_16_BIT] = SampleCoverage(6u, 11u); // !<
3062 }
3063 
iterate(void)3064 tcu::TestStatus SampleMaskWithDepthTestInstance::iterate(void)
3065 {
3066     de::MovePtr<tcu::TextureLevel> result;
3067 
3068     MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat,
3069                                  m_renderSize, m_useDepth, m_useStencil, 1u, &m_topology, &m_vertices,
3070                                  m_multisampleStateParams, m_blendState, m_renderType, m_imageBackingMode,
3071                                  m_useFragmentShadingRate, m_depthClearValue);
3072     result = renderer.render();
3073 
3074     return verifyImage(result->getAccess());
3075 }
3076 
getMultisampleState(const VkSampleCountFlagBits rasterizationSamples)3077 VkPipelineMultisampleStateCreateInfo SampleMaskWithDepthTestInstance::getMultisampleState(
3078     const VkSampleCountFlagBits rasterizationSamples)
3079 {
3080     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
3081         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
3082         DE_NULL,                                                  // const void* pNext;
3083         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
3084         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
3085         false,                                                    // VkBool32 sampleShadingEnable;
3086         0.0f,                                                     // float minSampleShading;
3087         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
3088         false,                                                    // VkBool32 alphaToCoverageEnable;
3089         false                                                     // VkBool32 alphaToOneEnable;
3090     };
3091 
3092     return multisampleStateParams;
3093 }
3094 
generateVertices(void)3095 std::vector<Vertex4RGBA> SampleMaskWithDepthTestInstance::generateVertices(void)
3096 {
3097     std::vector<Vertex4RGBA> vertices;
3098 
3099     {
3100         const Vertex4RGBA vertexInput = {tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), m_renderColor};
3101         vertices.push_back(vertexInput);
3102     }
3103     {
3104         const Vertex4RGBA vertexInput = {tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), m_renderColor};
3105         vertices.push_back(vertexInput);
3106     }
3107     {
3108         const Vertex4RGBA vertexInput = {tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), m_renderColor};
3109         vertices.push_back(vertexInput);
3110     }
3111 
3112     return vertices;
3113 }
3114 
verifyImage(const tcu::ConstPixelBufferAccess & result)3115 tcu::TestStatus SampleMaskWithDepthTestInstance::verifyImage(const tcu::ConstPixelBufferAccess &result)
3116 {
3117     bool pass         = true;
3118     const int width   = result.getWidth();
3119     const int height  = result.getHeight();
3120     tcu::TestLog &log = m_context.getTestContext().getLog();
3121 
3122     DE_ASSERT(width == 3);
3123     DE_ASSERT(height == 3);
3124 
3125     const tcu::Vec4 clearColor = tcu::Vec4(0.0f);
3126 
3127     for (int x = 0; x < width; ++x)
3128         for (int y = 0; y < height; ++y)
3129         {
3130             const tcu::Vec4 resultPixel = result.getPixel(x, y);
3131 
3132             if (x + y == 0)
3133             {
3134                 const float threshold   = 0.02f;
3135                 tcu::Vec4 expectedPixel = m_renderColor;
3136 
3137                 if (m_useFragmentShadingRate && m_enablePostDepthCoverage)
3138                 {
3139                     // The fragment shader for this test outputs a fragment value that
3140                     // is based off gl_SampleMaskIn. For the FSR case that sample mask
3141                     // applies to 4 pixels, rather than the usual 1 pixel per fragment
3142                     // shader invocation. Those 4 pixels represent:
3143                     //   a) The fully covered pixel (this "x + y == 0" case)
3144                     //   b) The two partially covered pixels (the "x + y == 1" case below)
3145                     //   c) The non-covered pixel (the "else" case below)
3146                     //
3147                     // For the PostDepthCoverage case, the gl_SampleMaskIn represents
3148                     // coverage after the depth test, so it has roughly 50% of the bits
3149                     // set. This means that the expected result for this case (a)
3150                     // will not be the "m_renderColor" but ~50% of the m_renderColor.
3151                     expectedPixel = expectedPixel * tcu::Vec4(0.5f);
3152                 }
3153 
3154                 bool localPass = true;
3155                 for (uint32_t componentNdx = 0u; componentNdx < m_renderColor.SIZE; ++componentNdx)
3156                 {
3157                     if (m_renderColor[componentNdx] != 0.0f &&
3158                         (resultPixel[componentNdx] <= expectedPixel[componentNdx] * (1.0f - threshold) ||
3159                          resultPixel[componentNdx] >= expectedPixel[componentNdx] * (1.0f + threshold)))
3160                         localPass = false;
3161                 }
3162 
3163                 if (!localPass)
3164                 {
3165                     log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3166                         << " Reference range ( " << expectedPixel * (1.0f - threshold) << " ; "
3167                         << expectedPixel * (1.0f + threshold) << " )" << tcu::TestLog::EndMessage;
3168                     pass = false;
3169                 }
3170             }
3171             else if (x + y == 1)
3172             {
3173                 const float threshold = 0.02f;
3174                 float minCoverage =
3175                     (float)m_refCoverageAfterDepthTest[m_rasterizationSamples].min / (float)m_rasterizationSamples;
3176                 float maxCoverage =
3177                     (float)m_refCoverageAfterDepthTest[m_rasterizationSamples].max / (float)m_rasterizationSamples;
3178 
3179                 // default: m_rasterizationSamples bits set in FS's gl_SampleMaskIn[0] (before depth test)
3180                 // post_depth_coverage: m_refCoverageAfterDepthTest[m_rasterizationSamples] bits set in FS's gl_SampleMaskIn[0] (after depth test)
3181 
3182                 if (m_enablePostDepthCoverage)
3183                 {
3184                     minCoverage *= minCoverage;
3185                     maxCoverage *= maxCoverage;
3186                 }
3187 
3188                 bool localPass = true;
3189                 for (uint32_t componentNdx = 0u; componentNdx < m_renderColor.SIZE; ++componentNdx)
3190                 {
3191                     if (m_renderColor[componentNdx] != 0.0f &&
3192                         (resultPixel[componentNdx] <= m_renderColor[componentNdx] * (minCoverage - threshold) ||
3193                          resultPixel[componentNdx] >= m_renderColor[componentNdx] * (maxCoverage + threshold)))
3194                         localPass = false;
3195                 }
3196 
3197                 if (!localPass)
3198                 {
3199                     log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3200                         << " Reference range ( " << m_renderColor * (minCoverage - threshold) << " ; "
3201                         << m_renderColor * (maxCoverage + threshold) << " )" << tcu::TestLog::EndMessage;
3202                     pass = false;
3203                 }
3204             }
3205             else
3206             {
3207                 if (resultPixel != clearColor)
3208                 {
3209                     log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3210                         << " Reference: " << clearColor << tcu::TestLog::EndMessage;
3211                     pass = false;
3212                 }
3213             }
3214         }
3215 
3216     if (pass)
3217         return tcu::TestStatus::pass("Passed");
3218     else
3219         return tcu::TestStatus::fail("Failed");
3220 }
3221 #endif // CTS_USES_VULKANSC
3222 // MultisampleRenderer
3223 
MultisampleRenderer(Context & context,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,const tcu::IVec2 & renderSize,const VkPrimitiveTopology topology,const std::vector<Vertex4RGBA> & vertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,const RenderType renderType,const ImageBackingMode backingMode,const bool useFragmentShadingRate)3224 MultisampleRenderer::MultisampleRenderer(Context &context, const PipelineConstructionType pipelineConstructionType,
3225                                          const VkFormat colorFormat, const tcu::IVec2 &renderSize,
3226                                          const VkPrimitiveTopology topology, const std::vector<Vertex4RGBA> &vertices,
3227                                          const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
3228                                          const VkPipelineColorBlendAttachmentState &blendState,
3229                                          const RenderType renderType, const ImageBackingMode backingMode,
3230                                          const bool useFragmentShadingRate)
3231     : m_context(context)
3232     , m_pipelineConstructionType(pipelineConstructionType)
3233     , m_bindSemaphore(createSemaphore(context.getDeviceInterface(), context.getDevice()))
3234     , m_colorFormat(colorFormat)
3235     , m_depthStencilFormat(VK_FORMAT_UNDEFINED)
3236     , m_renderSize(renderSize)
3237     , m_useDepth(false)
3238     , m_useStencil(false)
3239     , m_useConservative(false)
3240     , m_multisampleStateParams(multisampleStateParams)
3241     , m_colorBlendState(blendState)
3242     , m_rasterizationConservativeStateCreateInfo()
3243     , m_renderType(renderType)
3244     , m_backingMode(backingMode)
3245     , m_depthClearValue(1.0f)
3246     , m_useFragmentShadingRate(useFragmentShadingRate)
3247 {
3248     initialize(context, 1u, &topology, &vertices);
3249 }
3250 
MultisampleRenderer(Context & context,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,const VkFormat depthStencilFormat,const tcu::IVec2 & renderSize,const bool useDepth,const bool useStencil,const uint32_t numTopologies,const VkPrimitiveTopology * pTopology,const std::vector<Vertex4RGBA> * pVertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,const RenderType renderType,const ImageBackingMode backingMode,const bool useFragmentShadingRate,const float depthClearValue)3251 MultisampleRenderer::MultisampleRenderer(Context &context, const PipelineConstructionType pipelineConstructionType,
3252                                          const VkFormat colorFormat, const VkFormat depthStencilFormat,
3253                                          const tcu::IVec2 &renderSize, const bool useDepth, const bool useStencil,
3254                                          const uint32_t numTopologies, const VkPrimitiveTopology *pTopology,
3255                                          const std::vector<Vertex4RGBA> *pVertices,
3256                                          const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
3257                                          const VkPipelineColorBlendAttachmentState &blendState,
3258                                          const RenderType renderType, const ImageBackingMode backingMode,
3259                                          const bool useFragmentShadingRate, const float depthClearValue)
3260     : m_context(context)
3261     , m_pipelineConstructionType(pipelineConstructionType)
3262     , m_bindSemaphore(createSemaphore(context.getDeviceInterface(), context.getDevice()))
3263     , m_colorFormat(colorFormat)
3264     , m_depthStencilFormat(depthStencilFormat)
3265     , m_renderSize(renderSize)
3266     , m_useDepth(useDepth)
3267     , m_useStencil(useStencil)
3268     , m_useConservative(false)
3269     , m_multisampleStateParams(multisampleStateParams)
3270     , m_colorBlendState(blendState)
3271     , m_rasterizationConservativeStateCreateInfo()
3272     , m_renderType(renderType)
3273     , m_backingMode(backingMode)
3274     , m_depthClearValue(depthClearValue)
3275     , m_useFragmentShadingRate(useFragmentShadingRate)
3276 {
3277     initialize(context, numTopologies, pTopology, pVertices);
3278 }
3279 
MultisampleRenderer(Context & context,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,const VkFormat depthStencilFormat,const tcu::IVec2 & renderSize,const bool useDepth,const bool useStencil,const bool useConservative,const bool useFragmentShadingRate,const uint32_t numTopologies,const VkPrimitiveTopology * pTopology,const std::vector<Vertex4RGBA> * pVertices,const VkPipelineMultisampleStateCreateInfo & multisampleStateParams,const VkPipelineColorBlendAttachmentState & blendState,const VkPipelineRasterizationConservativeStateCreateInfoEXT & conservativeStateCreateInfo,const RenderType renderType,const ImageBackingMode backingMode,const float depthClearValue)3280 MultisampleRenderer::MultisampleRenderer(
3281     Context &context, const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
3282     const VkFormat depthStencilFormat, const tcu::IVec2 &renderSize, const bool useDepth, const bool useStencil,
3283     const bool useConservative, const bool useFragmentShadingRate, const uint32_t numTopologies,
3284     const VkPrimitiveTopology *pTopology, const std::vector<Vertex4RGBA> *pVertices,
3285     const VkPipelineMultisampleStateCreateInfo &multisampleStateParams,
3286     const VkPipelineColorBlendAttachmentState &blendState,
3287     const VkPipelineRasterizationConservativeStateCreateInfoEXT &conservativeStateCreateInfo,
3288     const RenderType renderType, const ImageBackingMode backingMode, const float depthClearValue)
3289     : m_context(context)
3290     , m_pipelineConstructionType(pipelineConstructionType)
3291     , m_bindSemaphore(createSemaphore(context.getDeviceInterface(), context.getDevice()))
3292     , m_colorFormat(colorFormat)
3293     , m_depthStencilFormat(depthStencilFormat)
3294     , m_renderSize(renderSize)
3295     , m_useDepth(useDepth)
3296     , m_useStencil(useStencil)
3297     , m_useConservative(useConservative)
3298     , m_multisampleStateParams(multisampleStateParams)
3299     , m_colorBlendState(blendState)
3300     , m_rasterizationConservativeStateCreateInfo(conservativeStateCreateInfo)
3301     , m_renderType(renderType)
3302     , m_backingMode(backingMode)
3303     , m_depthClearValue(depthClearValue)
3304     , m_useFragmentShadingRate(useFragmentShadingRate)
3305 {
3306     initialize(context, numTopologies, pTopology, pVertices);
3307 }
3308 
initialize(Context & context,const uint32_t numTopologies,const VkPrimitiveTopology * pTopology,const std::vector<Vertex4RGBA> * pVertices)3309 void MultisampleRenderer::initialize(Context &context, const uint32_t numTopologies,
3310                                      const VkPrimitiveTopology *pTopology, const std::vector<Vertex4RGBA> *pVertices)
3311 {
3312     if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(),
3313                                 m_multisampleStateParams.rasterizationSamples))
3314         throw tcu::NotSupportedError("Unsupported number of rasterization samples");
3315 
3316     const InstanceInterface &vki            = context.getInstanceInterface();
3317     const DeviceInterface &vk               = context.getDeviceInterface();
3318     const VkPhysicalDevice physicalDevice   = context.getPhysicalDevice();
3319     const VkDevice vkDevice                 = context.getDevice();
3320     const VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
3321     const uint32_t queueFamilyIndices[] = {context.getUniversalQueueFamilyIndex(), context.getSparseQueueFamilyIndex()};
3322     const bool sparse                   = m_backingMode == IMAGE_BACKING_MODE_SPARSE;
3323     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
3324                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
3325     const VkImageCreateFlags imageCreateFlags =
3326         sparse ? (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) : 0u;
3327     const VkSharingMode sharingMode =
3328         (sparse && context.getUniversalQueueFamilyIndex() != context.getSparseQueueFamilyIndex()) ?
3329             VK_SHARING_MODE_CONCURRENT :
3330             VK_SHARING_MODE_EXCLUSIVE;
3331     Allocator &memAlloc         = m_context.getDefaultAllocator();
3332     const bool usesResolveImage = m_renderType == RENDER_TYPE_RESOLVE ||
3333                                   m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY ||
3334                                   m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT;
3335 
3336     if (sparse)
3337     {
3338         bool sparseSamplesSupported = false;
3339         switch (m_multisampleStateParams.rasterizationSamples)
3340         {
3341         case VK_SAMPLE_COUNT_1_BIT:
3342             sparseSamplesSupported = features.sparseResidencyImage2D;
3343             break;
3344         case VK_SAMPLE_COUNT_2_BIT:
3345             sparseSamplesSupported = features.sparseResidency2Samples;
3346             break;
3347         case VK_SAMPLE_COUNT_4_BIT:
3348             sparseSamplesSupported = features.sparseResidency4Samples;
3349             break;
3350         case VK_SAMPLE_COUNT_8_BIT:
3351             sparseSamplesSupported = features.sparseResidency8Samples;
3352             break;
3353         case VK_SAMPLE_COUNT_16_BIT:
3354             sparseSamplesSupported = features.sparseResidency16Samples;
3355             break;
3356         default:
3357             break;
3358         }
3359 
3360         if (!sparseSamplesSupported)
3361             throw tcu::NotSupportedError("Unsupported number of rasterization samples for sparse residency");
3362     }
3363 
3364     if (sparse && !context.getDeviceFeatures().sparseBinding)
3365         throw tcu::NotSupportedError("No sparseBinding support");
3366 
3367     // Create color image
3368     {
3369         const VkImageUsageFlags imageUsageFlags =
3370             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3371             (m_renderType == RENDER_TYPE_COPY_SAMPLES ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0u);
3372 
3373         const VkImageCreateInfo colorImageParams = {
3374             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                          // VkStructureType sType;
3375             DE_NULL,                                                      // const void* pNext;
3376             imageCreateFlags,                                             // VkImageCreateFlags flags;
3377             VK_IMAGE_TYPE_2D,                                             // VkImageType imageType;
3378             m_colorFormat,                                                // VkFormat format;
3379             {(uint32_t)m_renderSize.x(), (uint32_t)m_renderSize.y(), 1u}, // VkExtent3D extent;
3380             1u,                                                           // uint32_t mipLevels;
3381             1u,                                                           // uint32_t arrayLayers;
3382             m_multisampleStateParams.rasterizationSamples,                // VkSampleCountFlagBits samples;
3383             VK_IMAGE_TILING_OPTIMAL,                                      // VkImageTiling tiling;
3384             imageUsageFlags,                                              // VkImageUsageFlags usage;
3385             sharingMode,                                                  // VkSharingMode sharingMode;
3386             sharingMode == VK_SHARING_MODE_CONCURRENT ? 2u : 1u,          // uint32_t queueFamilyIndexCount;
3387             queueFamilyIndices,                                           // const uint32_t* pQueueFamilyIndices;
3388             VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout initialLayout;
3389         };
3390 
3391 #ifndef CTS_USES_VULKANSC
3392         if (sparse && !checkSparseImageFormatSupport(context.getPhysicalDevice(), context.getInstanceInterface(),
3393                                                      colorImageParams))
3394             TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
3395 #endif // CTS_USES_VULKANSC
3396 
3397         m_colorImage = createImage(vk, vkDevice, &colorImageParams);
3398 
3399         // Allocate and bind color image memory
3400         if (sparse)
3401         {
3402 #ifndef CTS_USES_VULKANSC
3403             allocateAndBindSparseImage(vk, vkDevice, context.getPhysicalDevice(), context.getInstanceInterface(),
3404                                        colorImageParams, *m_bindSemaphore, context.getSparseQueue(), memAlloc,
3405                                        m_allocations, mapVkFormat(m_colorFormat), *m_colorImage);
3406 #endif // CTS_USES_VULKANSC
3407         }
3408         else
3409         {
3410             m_colorImageAlloc =
3411                 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
3412             VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
3413                                         m_colorImageAlloc->getOffset()));
3414         }
3415     }
3416 
3417     // Create resolve image
3418     if (usesResolveImage)
3419     {
3420         const VkImageCreateInfo resolveImageParams = {
3421             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                    // VkStructureType sType;
3422             DE_NULL,                                                                // const void* pNext;
3423             0u,                                                                     // VkImageCreateFlags flags;
3424             VK_IMAGE_TYPE_2D,                                                       // VkImageType imageType;
3425             m_colorFormat,                                                          // VkFormat format;
3426             {(uint32_t)m_renderSize.x(), (uint32_t)m_renderSize.y(), 1u},           // VkExtent3D extent;
3427             1u,                                                                     // uint32_t mipLevels;
3428             1u,                                                                     // uint32_t arrayLayers;
3429             VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits samples;
3430             VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling tiling;
3431             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | // VkImageUsageFlags usage;
3432                 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3433             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3434             1u,                        // uint32_t queueFamilyIndexCount;
3435             queueFamilyIndices,        // const uint32_t* pQueueFamilyIndices;
3436             VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout initialLayout;
3437         };
3438 
3439         m_resolveImage = createImage(vk, vkDevice, &resolveImageParams);
3440 
3441         // Allocate and bind resolve image memory
3442         m_resolveImageAlloc =
3443             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_resolveImage), MemoryRequirement::Any);
3444         VK_CHECK(vk.bindImageMemory(vkDevice, *m_resolveImage, m_resolveImageAlloc->getMemory(),
3445                                     m_resolveImageAlloc->getOffset()));
3446 
3447         // Create resolve attachment view
3448         {
3449             const VkImageViewCreateInfo resolveAttachmentViewParams = {
3450                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
3451                 DE_NULL,                                    // const void* pNext;
3452                 0u,                                         // VkImageViewCreateFlags flags;
3453                 *m_resolveImage,                            // VkImage image;
3454                 VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
3455                 m_colorFormat,                              // VkFormat format;
3456                 componentMappingRGBA,                       // VkComponentMapping components;
3457                 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
3458             };
3459 
3460             m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
3461         }
3462     }
3463 
3464     // Create per-sample output images
3465     if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3466     {
3467         const VkImageCreateInfo perSampleImageParams = {
3468             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                    // VkStructureType sType;
3469             DE_NULL,                                                                // const void* pNext;
3470             0u,                                                                     // VkImageCreateFlags flags;
3471             VK_IMAGE_TYPE_2D,                                                       // VkImageType imageType;
3472             m_colorFormat,                                                          // VkFormat format;
3473             {(uint32_t)m_renderSize.x(), (uint32_t)m_renderSize.y(), 1u},           // VkExtent3D extent;
3474             1u,                                                                     // uint32_t mipLevels;
3475             1u,                                                                     // uint32_t arrayLayers;
3476             VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits samples;
3477             VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling tiling;
3478             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | // VkImageUsageFlags usage;
3479                 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3480             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3481             1u,                        // uint32_t queueFamilyIndexCount;
3482             queueFamilyIndices,        // const uint32_t* pQueueFamilyIndices;
3483             VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout initialLayout;
3484         };
3485 
3486         m_perSampleImages.resize(static_cast<size_t>(m_multisampleStateParams.rasterizationSamples));
3487 
3488         for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3489         {
3490             m_perSampleImages[i]  = de::SharedPtr<PerSampleImage>(new PerSampleImage);
3491             PerSampleImage &image = *m_perSampleImages[i];
3492 
3493             image.m_image = createImage(vk, vkDevice, &perSampleImageParams);
3494 
3495             // Allocate and bind image memory
3496             image.m_imageAlloc =
3497                 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image.m_image), MemoryRequirement::Any);
3498             VK_CHECK(vk.bindImageMemory(vkDevice, *image.m_image, image.m_imageAlloc->getMemory(),
3499                                         image.m_imageAlloc->getOffset()));
3500 
3501             // Create per-sample attachment view
3502             {
3503                 const VkImageViewCreateInfo perSampleAttachmentViewParams = {
3504                     VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
3505                     DE_NULL,                                    // const void* pNext;
3506                     0u,                                         // VkImageViewCreateFlags flags;
3507                     *image.m_image,                             // VkImage image;
3508                     VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
3509                     m_colorFormat,                              // VkFormat format;
3510                     componentMappingRGBA,                       // VkComponentMapping components;
3511                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
3512                 };
3513 
3514                 image.m_attachmentView = createImageView(vk, vkDevice, &perSampleAttachmentViewParams);
3515             }
3516         }
3517     }
3518 
3519     // Create a depth/stencil image
3520     if (m_useDepth || m_useStencil)
3521     {
3522         const VkImageCreateInfo depthStencilImageParams = {
3523             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                          // VkStructureType sType;
3524             DE_NULL,                                                      // const void* pNext;
3525             0u,                                                           // VkImageCreateFlags flags;
3526             VK_IMAGE_TYPE_2D,                                             // VkImageType imageType;
3527             m_depthStencilFormat,                                         // VkFormat format;
3528             {(uint32_t)m_renderSize.x(), (uint32_t)m_renderSize.y(), 1u}, // VkExtent3D extent;
3529             1u,                                                           // uint32_t mipLevels;
3530             1u,                                                           // uint32_t arrayLayers;
3531             m_multisampleStateParams.rasterizationSamples,                // VkSampleCountFlagBits samples;
3532             VK_IMAGE_TILING_OPTIMAL,                                      // VkImageTiling tiling;
3533             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,                  // VkImageUsageFlags usage;
3534             VK_SHARING_MODE_EXCLUSIVE,                                    // VkSharingMode sharingMode;
3535             1u,                                                           // uint32_t queueFamilyIndexCount;
3536             queueFamilyIndices,                                           // const uint32_t* pQueueFamilyIndices;
3537             VK_IMAGE_LAYOUT_UNDEFINED                                     // VkImageLayout initialLayout;
3538         };
3539 
3540         m_depthStencilImage = createImage(vk, vkDevice, &depthStencilImageParams);
3541 
3542         // Allocate and bind depth/stencil image memory
3543         m_depthStencilImageAlloc =
3544             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthStencilImage), MemoryRequirement::Any);
3545         VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthStencilImage, m_depthStencilImageAlloc->getMemory(),
3546                                     m_depthStencilImageAlloc->getOffset()));
3547     }
3548 
3549     // Create color attachment view
3550     {
3551         const VkImageViewCreateInfo colorAttachmentViewParams = {
3552             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
3553             DE_NULL,                                    // const void* pNext;
3554             0u,                                         // VkImageViewCreateFlags flags;
3555             *m_colorImage,                              // VkImage image;
3556             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
3557             m_colorFormat,                              // VkFormat format;
3558             componentMappingRGBA,                       // VkComponentMapping components;
3559             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
3560         };
3561 
3562         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
3563     }
3564 
3565     VkImageAspectFlags depthStencilAttachmentAspect = (VkImageAspectFlagBits)0;
3566 
3567     // Create depth/stencil attachment view
3568     if (m_useDepth || m_useStencil)
3569     {
3570         depthStencilAttachmentAspect = getImageAspectFlags(m_depthStencilFormat);
3571 
3572         const VkImageViewCreateInfo depthStencilAttachmentViewParams = {
3573             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,      // VkStructureType sType;
3574             DE_NULL,                                       // const void* pNext;
3575             0u,                                            // VkImageViewCreateFlags flags;
3576             *m_depthStencilImage,                          // VkImage image;
3577             VK_IMAGE_VIEW_TYPE_2D,                         // VkImageViewType viewType;
3578             m_depthStencilFormat,                          // VkFormat format;
3579             componentMappingRGBA,                          // VkComponentMapping components;
3580             {depthStencilAttachmentAspect, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
3581         };
3582 
3583         m_depthStencilAttachmentView = createImageView(vk, vkDevice, &depthStencilAttachmentViewParams);
3584     }
3585 
3586     // Create render pass
3587     {
3588         std::vector<VkAttachmentDescription> attachmentDescriptions;
3589         {
3590             const VkAttachmentDescription colorAttachmentDescription = {
3591                 0u,                                            // VkAttachmentDescriptionFlags flags;
3592                 m_colorFormat,                                 // VkFormat format;
3593                 m_multisampleStateParams.rasterizationSamples, // VkSampleCountFlagBits samples;
3594                 VK_ATTACHMENT_LOAD_OP_CLEAR,                   // VkAttachmentLoadOp loadOp;
3595                 VK_ATTACHMENT_STORE_OP_STORE,                  // VkAttachmentStoreOp storeOp;
3596                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,               // VkAttachmentLoadOp stencilLoadOp;
3597                 VK_ATTACHMENT_STORE_OP_DONT_CARE,              // VkAttachmentStoreOp stencilStoreOp;
3598                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,      // VkImageLayout initialLayout;
3599                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL       // VkImageLayout finalLayout;
3600             };
3601             attachmentDescriptions.push_back(colorAttachmentDescription);
3602         }
3603 
3604         uint32_t resolveAttachmentIndex = VK_ATTACHMENT_UNUSED;
3605 
3606         if (usesResolveImage)
3607         {
3608             resolveAttachmentIndex = static_cast<uint32_t>(attachmentDescriptions.size());
3609 
3610             const VkAttachmentDescription resolveAttachmentDescription = {
3611                 0u,                                       // VkAttachmentDescriptionFlags flags;
3612                 m_colorFormat,                            // VkFormat format;
3613                 VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
3614                 VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
3615                 VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
3616                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
3617                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
3618                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
3619                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout finalLayout;
3620             };
3621             attachmentDescriptions.push_back(resolveAttachmentDescription);
3622         }
3623 
3624         uint32_t perSampleAttachmentIndex = VK_ATTACHMENT_UNUSED;
3625 
3626         if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3627         {
3628             perSampleAttachmentIndex = static_cast<uint32_t>(attachmentDescriptions.size());
3629 
3630             const VkAttachmentDescription perSampleAttachmentDescription = {
3631                 0u,                                       // VkAttachmentDescriptionFlags flags;
3632                 m_colorFormat,                            // VkFormat format;
3633                 VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
3634                 VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
3635                 VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
3636                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
3637                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
3638                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
3639                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout finalLayout;
3640             };
3641 
3642             for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3643             {
3644                 attachmentDescriptions.push_back(perSampleAttachmentDescription);
3645             }
3646         }
3647 
3648         uint32_t depthStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
3649 
3650         if (m_useDepth || m_useStencil)
3651         {
3652             depthStencilAttachmentIndex = static_cast<uint32_t>(attachmentDescriptions.size());
3653 
3654             const VkAttachmentDescription depthStencilAttachmentDescription = {
3655                 0u,                                            // VkAttachmentDescriptionFlags flags;
3656                 m_depthStencilFormat,                          // VkFormat format;
3657                 m_multisampleStateParams.rasterizationSamples, // VkSampleCountFlagBits samples;
3658                 (m_useDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR :
3659                               VK_ATTACHMENT_LOAD_OP_DONT_CARE), // VkAttachmentLoadOp loadOp;
3660                 (m_useDepth ? VK_ATTACHMENT_STORE_OP_STORE :
3661                               VK_ATTACHMENT_STORE_OP_DONT_CARE), // VkAttachmentStoreOp storeOp;
3662                 (m_useStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR :
3663                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE), // VkAttachmentStoreOp stencilLoadOp;
3664                 (m_useStencil ? VK_ATTACHMENT_STORE_OP_STORE :
3665                                 VK_ATTACHMENT_STORE_OP_DONT_CARE), // VkAttachmentStoreOp stencilStoreOp;
3666                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,  // VkImageLayout initialLayout;
3667                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL   // VkImageLayout finalLayout;
3668             };
3669             attachmentDescriptions.push_back(depthStencilAttachmentDescription);
3670         }
3671 
3672         const VkAttachmentReference colorAttachmentReference = {
3673             0u,                                      // uint32_t attachment;
3674             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
3675         };
3676 
3677         const VkAttachmentReference inputAttachmentReference = {
3678             0u,                                      // uint32_t attachment;
3679             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout layout;
3680         };
3681 
3682         const VkAttachmentReference resolveAttachmentReference = {
3683             resolveAttachmentIndex,                  // uint32_t attachment;
3684             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
3685         };
3686 
3687         const VkAttachmentReference colorAttachmentReferencesUnusedAttachment[] = {
3688             {
3689                 VK_ATTACHMENT_UNUSED,     // uint32_t            attachment
3690                 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout    layout
3691             },
3692             {
3693                 0u,                                      // uint32_t            attachment
3694                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout
3695             }};
3696 
3697         const VkAttachmentReference resolveAttachmentReferencesUnusedAttachment[] = {
3698             {
3699                 VK_ATTACHMENT_UNUSED,     // uint32_t            attachment
3700                 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout    layout
3701             },
3702             {
3703                 resolveAttachmentIndex,                  // uint32_t            attachment
3704                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout
3705             }};
3706 
3707         std::vector<VkAttachmentReference> perSampleAttachmentReferences(m_perSampleImages.size());
3708         if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3709         {
3710             for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3711             {
3712                 const VkAttachmentReference perSampleAttachmentReference = {
3713                     perSampleAttachmentIndex + static_cast<uint32_t>(i), // uint32_t attachment;
3714                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL             // VkImageLayout layout;
3715                 };
3716                 perSampleAttachmentReferences[i] = perSampleAttachmentReference;
3717             }
3718         }
3719 
3720         const VkAttachmentReference depthStencilAttachmentReference = {
3721             depthStencilAttachmentIndex,                     // uint32_t attachment;
3722             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
3723         };
3724 
3725         std::vector<VkSubpassDescription> subpassDescriptions;
3726         std::vector<VkSubpassDependency> subpassDependencies;
3727 
3728         if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
3729         {
3730             const VkSubpassDescription subpassDescription0 = {
3731                 0u,                               // VkSubpassDescriptionFlags    flags
3732                 VK_PIPELINE_BIND_POINT_GRAPHICS,  // VkPipelineBindPoint            pipelineBindPoint
3733                 0u,                               // uint32_t                        inputAttachmentCount
3734                 DE_NULL,                          // const VkAttachmentReference*    pInputAttachments
3735                 0u,                               // uint32_t                        colorAttachmentCount
3736                 DE_NULL,                          // const VkAttachmentReference*    pColorAttachments
3737                 DE_NULL,                          // const VkAttachmentReference*    pResolveAttachments
3738                 &depthStencilAttachmentReference, // const VkAttachmentReference*    pDepthStencilAttachment
3739                 0u,                               // uint32_t                        preserveAttachmentCount
3740                 DE_NULL                           // const VkAttachmentReference*    pPreserveAttachments
3741             };
3742 
3743             const VkSubpassDescription subpassDescription1 = {
3744                 0u,                               // VkSubpassDescriptionFlags    flags
3745                 VK_PIPELINE_BIND_POINT_GRAPHICS,  // VkPipelineBindPoint            pipelineBindPoint
3746                 0u,                               // uint32_t                        inputAttachmentCount
3747                 DE_NULL,                          // const VkAttachmentReference*    pInputAttachments
3748                 1u,                               // uint32_t                        colorAttachmentCount
3749                 &colorAttachmentReference,        // const VkAttachmentReference*    pColorAttachments
3750                 &resolveAttachmentReference,      // const VkAttachmentReference*    pResolveAttachments
3751                 &depthStencilAttachmentReference, // const VkAttachmentReference*    pDepthStencilAttachment
3752                 0u,                               // uint32_t                        preserveAttachmentCount
3753                 DE_NULL                           // const VkAttachmentReference*    pPreserveAttachments
3754             };
3755 
3756             const VkSubpassDependency subpassDependency = {
3757                 0u,                                           // uint32_t                srcSubpass
3758                 1u,                                           // uint32_t                dstSubpass
3759                 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,    // VkPipelineStageFlags    srcStageMask
3760                 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,    // VkPipelineStageFlags    dstStageMask
3761                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags        srcAccessMask
3762                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,  // VkAccessFlags        dstAccessMask
3763                 0u                                            // VkDependencyFlags    dependencyFlags
3764             };
3765 
3766             subpassDescriptions.push_back(subpassDescription0);
3767             subpassDescriptions.push_back(subpassDescription1);
3768             subpassDependencies.push_back(subpassDependency);
3769         }
3770         else if (m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT)
3771         {
3772             const VkSubpassDescription renderSubpassDescription = {
3773                 0u,                                          // VkSubpassDescriptionFlags    flags
3774                 VK_PIPELINE_BIND_POINT_GRAPHICS,             // VkPipelineBindPoint            pipelineBindPoint
3775                 0u,                                          // uint32_t                        inputAttachmentCount
3776                 DE_NULL,                                     // const VkAttachmentReference*    pInputAttachments
3777                 2u,                                          // uint32_t                        colorAttachmentCount
3778                 colorAttachmentReferencesUnusedAttachment,   // const VkAttachmentReference*    pColorAttachments
3779                 resolveAttachmentReferencesUnusedAttachment, // const VkAttachmentReference*    pResolveAttachments
3780                 DE_NULL,                                     // const VkAttachmentReference*    pDepthStencilAttachment
3781                 0u,                                          // uint32_t                        preserveAttachmentCount
3782                 DE_NULL                                      // const VkAttachmentReference*    pPreserveAttachments
3783             };
3784 
3785             subpassDescriptions.push_back(renderSubpassDescription);
3786         }
3787         else
3788         {
3789             {
3790                 const VkSubpassDescription renderSubpassDescription = {
3791                     0u,                              // VkSubpassDescriptionFlags flags;
3792                     VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
3793                     0u,                              // uint32_t inputAttachmentCount;
3794                     DE_NULL,                         // const VkAttachmentReference* pInputAttachments;
3795                     1u,                              // uint32_t colorAttachmentCount;
3796                     &colorAttachmentReference,       // const VkAttachmentReference* pColorAttachments;
3797                     usesResolveImage ? &resolveAttachmentReference :
3798                                        DE_NULL, // const VkAttachmentReference* pResolveAttachments;
3799                     (m_useDepth || m_useStencil ? &depthStencilAttachmentReference :
3800                                                   DE_NULL), // const VkAttachmentReference* pDepthStencilAttachment;
3801                     0u,                                     // uint32_t preserveAttachmentCount;
3802                     DE_NULL                                 // const VkAttachmentReference* pPreserveAttachments;
3803                 };
3804                 subpassDescriptions.push_back(renderSubpassDescription);
3805             }
3806 
3807             if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3808             {
3809 
3810                 for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3811                 {
3812                     const VkSubpassDescription copySampleSubpassDescription = {
3813                         0u,                                // VkSubpassDescriptionFlags flags;
3814                         VK_PIPELINE_BIND_POINT_GRAPHICS,   // VkPipelineBindPoint pipelineBindPoint;
3815                         1u,                                // uint32_t inputAttachmentCount;
3816                         &inputAttachmentReference,         // const VkAttachmentReference* pInputAttachments;
3817                         1u,                                // uint32_t colorAttachmentCount;
3818                         &perSampleAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
3819                         DE_NULL,                           // const VkAttachmentReference* pResolveAttachments;
3820                         DE_NULL,                           // const VkAttachmentReference* pDepthStencilAttachment;
3821                         0u,                                // uint32_t preserveAttachmentCount;
3822                         DE_NULL                            // const VkAttachmentReference* pPreserveAttachments;
3823                     };
3824                     subpassDescriptions.push_back(copySampleSubpassDescription);
3825 
3826                     const VkSubpassDependency copySampleSubpassDependency = {
3827                         0u,                                            // uint32_t                            srcSubpass
3828                         1u + static_cast<uint32_t>(i),                 // uint32_t                            dstSubpass
3829                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags                srcStageMask
3830                         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags                dstStageMask
3831                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,  // VkAccessFlags                    srcAccessMask
3832                         VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,   // VkAccessFlags                    dstAccessMask
3833                         0u,                                    // VkDependencyFlags                dependencyFlags
3834                     };
3835                     subpassDependencies.push_back(copySampleSubpassDependency);
3836                 }
3837                 // the very last sample pass must synchronize with all prior subpasses
3838                 for (size_t i = 0; i < (m_perSampleImages.size() - 1); ++i)
3839                 {
3840                     const VkSubpassDependency storeSubpassDependency = {
3841                         1u + static_cast<uint32_t>(i), // uint32_t                            srcSubpass
3842                         static_cast<uint32_t>(
3843                             m_perSampleImages.size()),                 // uint32_t                            dstSubpass
3844                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags                srcStageMask
3845                         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags                dstStageMask
3846                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,  // VkAccessFlags                    srcAccessMask
3847                         VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,   // VkAccessFlags                    dstAccessMask
3848                         0u,                                    // VkDependencyFlags                dependencyFlags
3849                     };
3850                     subpassDependencies.push_back(storeSubpassDependency);
3851                 }
3852             }
3853         }
3854 
3855         const VkRenderPassCreateInfo renderPassParams = {
3856             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
3857             DE_NULL,                                   // const void* pNext;
3858             0u,                                        // VkRenderPassCreateFlags flags;
3859             (uint32_t)attachmentDescriptions.size(),   // uint32_t attachmentCount;
3860             &attachmentDescriptions[0],                // const VkAttachmentDescription* pAttachments;
3861             (uint32_t)subpassDescriptions.size(),      // uint32_t subpassCount;
3862             &subpassDescriptions[0],                   // const VkSubpassDescription* pSubpasses;
3863             (uint32_t)subpassDependencies.size(),      // uint32_t dependencyCount;
3864             subpassDependencies.size() != 0 ? &subpassDependencies[0] : DE_NULL};
3865 
3866         m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
3867     }
3868 
3869     // Create framebuffer
3870     {
3871         std::vector<VkImage> images;
3872         std::vector<VkImageView> attachments;
3873         images.push_back(*m_colorImage);
3874         attachments.push_back(*m_colorAttachmentView);
3875         if (usesResolveImage)
3876         {
3877             images.push_back(*m_resolveImage);
3878             attachments.push_back(*m_resolveAttachmentView);
3879         }
3880         if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3881         {
3882             for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3883             {
3884                 images.push_back(*m_perSampleImages[i]->m_image);
3885                 attachments.push_back(*m_perSampleImages[i]->m_attachmentView);
3886             }
3887         }
3888 
3889         if (m_useDepth || m_useStencil)
3890         {
3891             images.push_back(*m_depthStencilImage);
3892             attachments.push_back(*m_depthStencilAttachmentView);
3893         }
3894 
3895         const VkFramebufferCreateInfo framebufferParams = {
3896             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
3897             DE_NULL,                                   // const void* pNext;
3898             0u,                                        // VkFramebufferCreateFlags flags;
3899             *m_renderPass,                             // VkRenderPass renderPass;
3900             (uint32_t)attachments.size(),              // uint32_t attachmentCount;
3901             &attachments[0],                           // const VkImageView* pAttachments;
3902             (uint32_t)m_renderSize.x(),                // uint32_t width;
3903             (uint32_t)m_renderSize.y(),                // uint32_t height;
3904             1u                                         // uint32_t layers;
3905         };
3906 
3907         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
3908     }
3909 
3910     // Create pipeline layout
3911     {
3912         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
3913             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
3914             DE_NULL,                                       // const void* pNext;
3915             0u,                                            // VkPipelineLayoutCreateFlags flags;
3916             0u,                                            // uint32_t setLayoutCount;
3917             DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
3918             0u,                                            // uint32_t pushConstantRangeCount;
3919             DE_NULL                                        // const VkPushConstantRange* pPushConstantRanges;
3920         };
3921 
3922         m_pipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
3923 
3924         if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3925         {
3926 
3927             // Create descriptor set layout
3928             const VkDescriptorSetLayoutBinding layoutBinding = {
3929                 0u,                                  // uint32_t binding;
3930                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
3931                 1u,                                  // uint32_t descriptorCount;
3932                 VK_SHADER_STAGE_FRAGMENT_BIT,        // VkShaderStageFlags stageFlags;
3933                 DE_NULL,                             // const VkSampler* pImmutableSamplers;
3934             };
3935 
3936             const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
3937                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
3938                 DE_NULL,                                             // const void*                            pNext
3939                 0u,                                                  // VkDescriptorSetLayoutCreateFlags        flags
3940                 1u,            // uint32_t                                bindingCount
3941                 &layoutBinding // const VkDescriptorSetLayoutBinding*    pBindings
3942             };
3943             m_copySampleDesciptorLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
3944 
3945             // Create pipeline layout
3946 
3947             const VkPushConstantRange pushConstantRange = {
3948                 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
3949                 0u,                           // uint32_t offset;
3950                 sizeof(int32_t)               // uint32_t size;
3951             };
3952             const VkPipelineLayoutCreateInfo copySamplePipelineLayoutParams = {
3953                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
3954                 DE_NULL,                                       // const void* pNext;
3955                 0u,                                            // VkPipelineLayoutCreateFlags flags;
3956                 1u,                                            // uint32_t setLayoutCount;
3957                 &m_copySampleDesciptorLayout.get(),            // const VkDescriptorSetLayout* pSetLayouts;
3958                 1u,                                            // uint32_t pushConstantRangeCount;
3959                 &pushConstantRange                             // const VkPushConstantRange* pPushConstantRanges;
3960             };
3961             m_copySamplePipelineLayout =
3962                 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &copySamplePipelineLayoutParams);
3963         }
3964     }
3965 
3966     m_vertexShaderModule   = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
3967     m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
3968 
3969     if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3970     {
3971         m_copySampleVertexShaderModule =
3972             ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("quad_vert"), 0);
3973         m_copySampleFragmentShaderModule =
3974             ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("copy_sample_frag"), 0);
3975     }
3976 
3977     // Create pipeline
3978     {
3979         const VkVertexInputBindingDescription vertexInputBindingDescription = {
3980             0u,                         // uint32_t binding;
3981             sizeof(Vertex4RGBA),        // uint32_t stride;
3982             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
3983         };
3984 
3985         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
3986             {
3987                 0u,                            // uint32_t location;
3988                 0u,                            // uint32_t binding;
3989                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
3990                 0u                             // uint32_t offset;
3991             },
3992             {
3993                 1u,                            // uint32_t location;
3994                 0u,                            // uint32_t binding;
3995                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
3996                 offsetof(Vertex4RGBA, color),  // uint32_t offset;
3997             }};
3998 
3999         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
4000             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
4001             DE_NULL,                                                   // const void* pNext;
4002             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
4003             1u,                                                        // uint32_t vertexBindingDescriptionCount;
4004             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
4005             2u,                              // uint32_t vertexAttributeDescriptionCount;
4006             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
4007         };
4008 
4009         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
4010         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
4011 
4012         const uint32_t attachmentCount = m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT ? 2u : 1u;
4013 
4014         std::vector<VkPipelineColorBlendAttachmentState> attachments;
4015 
4016         for (uint32_t attachmentIdx = 0; attachmentIdx < attachmentCount; attachmentIdx++)
4017             attachments.push_back(m_colorBlendState);
4018 
4019         VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
4020             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
4021             DE_NULL,                                                  // const void* pNext;
4022             0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
4023             false,                                                    // VkBool32 logicOpEnable;
4024             VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
4025             attachmentCount,                                          // uint32_t attachmentCount;
4026             attachments.data(),      // const VkPipelineColorBlendAttachmentState* pAttachments;
4027             {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
4028         };
4029 
4030         const VkStencilOpState stencilOpState = {
4031             VK_STENCIL_OP_KEEP,    // VkStencilOp failOp;
4032             VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
4033             VK_STENCIL_OP_KEEP,    // VkStencilOp depthFailOp;
4034             VK_COMPARE_OP_GREATER, // VkCompareOp compareOp;
4035             1u,                    // uint32_t compareMask;
4036             1u,                    // uint32_t writeMask;
4037             1u,                    // uint32_t reference;
4038         };
4039 
4040         const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = {
4041             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
4042             DE_NULL,                                                    // const void* pNext;
4043             0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
4044             m_useDepth,                                                 // VkBool32 depthTestEnable;
4045             m_useDepth,                                                 // VkBool32 depthWriteEnable;
4046             VK_COMPARE_OP_LESS,                                         // VkCompareOp depthCompareOp;
4047             false,                                                      // VkBool32 depthBoundsTestEnable;
4048             m_useStencil,                                               // VkBool32 stencilTestEnable;
4049             stencilOpState,                                             // VkStencilOpState front;
4050             stencilOpState,                                             // VkStencilOpState back;
4051             0.0f,                                                       // float minDepthBounds;
4052             1.0f,                                                       // float maxDepthBounds;
4053         };
4054 
4055         const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo{
4056             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                                sType
4057             m_useConservative ? &m_rasterizationConservativeStateCreateInfo :
4058                                 DE_NULL,     // const void*                                    pNext
4059             0u,                              // VkPipelineRasterizationStateCreateFlags        flags
4060             VK_FALSE,                        // VkBool32                                        depthClampEnable
4061             VK_FALSE,                        // VkBool32                                        rasterizerDiscardEnable
4062             VK_POLYGON_MODE_FILL,            // VkPolygonMode                                polygonMode
4063             VK_CULL_MODE_NONE,               // VkCullModeFlags                                cullMode
4064             VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace                                    frontFace
4065             VK_FALSE,                        // VkBool32                                        depthBiasEnable
4066             0.0f,                            // float                                        depthBiasConstantFactor
4067             0.0f,                            // float                                        depthBiasClamp
4068             0.0f,                            // float                                        depthBiasSlopeFactor
4069             1.0f                             // float                                        lineWidth
4070         };
4071 
4072         VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo{
4073             VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
4074             DE_NULL,                                                                // const void* pNext;
4075             {2, 2},                                                                 // VkExtent2D fragmentSize;
4076             {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
4077              VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
4078         };
4079 
4080         const uint32_t numSubpasses = m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY ? 2u : 1u;
4081 
4082         m_graphicsPipelines.reserve(numSubpasses * numTopologies);
4083         for (uint32_t subpassIdx = 0; subpassIdx < numSubpasses; subpassIdx++)
4084         {
4085             if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4086             {
4087                 if (subpassIdx == 0)
4088                 {
4089                     colorBlendStateParams.attachmentCount = 0;
4090                 }
4091                 else
4092                 {
4093                     colorBlendStateParams.attachmentCount = 1;
4094                 }
4095             }
4096             for (uint32_t i = 0u; i < numTopologies; ++i)
4097             {
4098                 m_graphicsPipelines.emplace_back(vki, vk, physicalDevice, vkDevice, context.getDeviceExtensions(),
4099                                                  m_pipelineConstructionType);
4100                 m_graphicsPipelines.back()
4101                     .setDefaultTopology(pTopology[i])
4102                     .setupVertexInputState(&vertexInputStateParams)
4103                     .setupPreRasterizationShaderState(
4104                         viewports, scissors, m_pipelineLayout, *m_renderPass, subpassIdx, m_vertexShaderModule,
4105                         &rasterizationStateCreateInfo, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL,
4106                         (m_useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr))
4107                     .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, subpassIdx, m_fragmentShaderModule,
4108                                               &depthStencilStateParams, &m_multisampleStateParams)
4109                     .setupFragmentOutputState(*m_renderPass, subpassIdx, &colorBlendStateParams,
4110                                               &m_multisampleStateParams)
4111                     .setMonolithicPipelineLayout(m_pipelineLayout)
4112                     .buildPipeline();
4113             }
4114         }
4115     }
4116 
4117     if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4118     {
4119         // Create pipelines for copying samples to single sampled images
4120         {
4121             const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
4122                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
4123                 DE_NULL,                                                   // const void* pNext;
4124                 0u,      // VkPipelineVertexInputStateCreateFlags flags;
4125                 0u,      // uint32_t vertexBindingDescriptionCount;
4126                 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
4127                 0u,      // uint32_t vertexAttributeDescriptionCount;
4128                 DE_NULL  // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
4129             };
4130 
4131             const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
4132             const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
4133 
4134             const VkPipelineColorBlendStateCreateInfo colorBlendStateParams{
4135                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
4136                 DE_NULL,                                                  // const void* pNext;
4137                 0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
4138                 false,                                                    // VkBool32 logicOpEnable;
4139                 VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
4140                 1u,                                                       // uint32_t attachmentCount;
4141                 &m_colorBlendState,      // const VkPipelineColorBlendAttachmentState* pAttachments;
4142                 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
4143             };
4144 
4145             m_copySamplePipelines.reserve(m_perSampleImages.size());
4146             for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4147             {
4148                 // Pipeline is to be used in subpasses subsequent to sample-shading subpass
4149 
4150                 const uint32_t subpassIdx = 1u + (uint32_t)i;
4151                 m_copySamplePipelines.emplace_back(vki, vk, physicalDevice, vkDevice, m_context.getDeviceExtensions(),
4152                                                    m_pipelineConstructionType);
4153                 m_copySamplePipelines.back()
4154                     .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
4155                     .setDefaultRasterizationState()
4156                     .setDefaultMultisampleState()
4157                     .setDefaultDepthStencilState()
4158                     .setupVertexInputState(&vertexInputStateParams)
4159                     .setupPreRasterizationShaderState(viewports, scissors, m_copySamplePipelineLayout, *m_renderPass,
4160                                                       subpassIdx, m_copySampleVertexShaderModule)
4161                     .setupFragmentShaderState(m_copySamplePipelineLayout, *m_renderPass, subpassIdx,
4162                                               m_copySampleFragmentShaderModule)
4163                     .setupFragmentOutputState(*m_renderPass, subpassIdx, &colorBlendStateParams)
4164                     .setMonolithicPipelineLayout(m_copySamplePipelineLayout)
4165                     .buildPipeline();
4166             }
4167         }
4168 
4169         const VkDescriptorPoolSize descriptorPoolSize{
4170             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType type;
4171             1u                                   // uint32_t descriptorCount;
4172         };
4173 
4174         const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
4175             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,     // VkStructureType                    sType
4176             DE_NULL,                                           // const void*                        pNext
4177             VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags        flags
4178             1u,                                                // uint32_t                            maxSets
4179             1u,                                                // uint32_t                            poolSizeCount
4180             &descriptorPoolSize                                // const VkDescriptorPoolSize*        pPoolSizes
4181         };
4182 
4183         m_copySampleDesciptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
4184 
4185         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
4186             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                    sType
4187             DE_NULL,                                        // const void*                        pNext
4188             *m_copySampleDesciptorPool,                     // VkDescriptorPool                    descriptorPool
4189             1u,                                             // uint32_t                            descriptorSetCount
4190             &m_copySampleDesciptorLayout.get(),             // const VkDescriptorSetLayout*        pSetLayouts
4191         };
4192 
4193         m_copySampleDesciptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
4194 
4195         const VkDescriptorImageInfo imageInfo{DE_NULL, *m_colorAttachmentView,
4196                                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
4197         const VkWriteDescriptorSet descriptorWrite{
4198             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
4199             DE_NULL,                                // const void* pNext;
4200             *m_copySampleDesciptorSet,              // VkDescriptorSet dstSet;
4201             0u,                                     // uint32_t dstBinding;
4202             0u,                                     // uint32_t dstArrayElement;
4203             1u,                                     // uint32_t descriptorCount;
4204             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,    // VkDescriptorType descriptorType;
4205             &imageInfo,                             // const VkDescriptorImageInfo* pImageInfo;
4206             DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
4207             DE_NULL,                                // const VkBufferView* pTexelBufferView;
4208         };
4209         vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
4210     }
4211 
4212     // Create vertex buffer
4213     {
4214         const VkBufferCreateInfo vertexBufferParams{
4215             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
4216             DE_NULL,                              // const void* pNext;
4217             0u,                                   // VkBufferCreateFlags flags;
4218             1024u,                                // VkDeviceSize size;
4219             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
4220             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
4221             1u,                                   // uint32_t queueFamilyIndexCount;
4222             &queueFamilyIndices[0]                // const uint32_t* pQueueFamilyIndices;
4223         };
4224 
4225         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
4226         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
4227                                                 MemoryRequirement::HostVisible);
4228 
4229         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
4230                                      m_vertexBufferAlloc->getOffset()));
4231 
4232         // Load vertices into vertex buffer
4233         {
4234             Vertex4RGBA *pDst = static_cast<Vertex4RGBA *>(m_vertexBufferAlloc->getHostPtr());
4235 
4236             if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4237             {
4238                 DE_ASSERT(numTopologies == 1);
4239 
4240                 std::vector<Vertex4RGBA> vertices = pVertices[0];
4241 
4242                 // Set alpha to zero for the first draw. This should prevent depth writes because of zero coverage.
4243                 for (size_t i = 0; i < vertices.size(); i++)
4244                     vertices[i].color.w() = 0.0f;
4245 
4246                 deMemcpy(pDst, &vertices[0], vertices.size() * sizeof(Vertex4RGBA));
4247 
4248                 pDst += vertices.size();
4249 
4250                 // The second draw uses original vertices which are pure red.
4251                 deMemcpy(pDst, &pVertices[0][0], pVertices[0].size() * sizeof(Vertex4RGBA));
4252             }
4253             else
4254             {
4255                 for (uint32_t i = 0u; i < numTopologies; ++i)
4256                 {
4257                     deMemcpy(pDst, &pVertices[i][0], pVertices[i].size() * sizeof(Vertex4RGBA));
4258                     pDst += pVertices[i].size();
4259                 }
4260             }
4261         }
4262         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
4263     }
4264 
4265     // Create command pool
4266     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndices[0]);
4267 
4268     // Create command buffer
4269     {
4270         VkClearValue colorClearValue;
4271         if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4272         {
4273             colorClearValue.color.float32[0] = 0.25;
4274             colorClearValue.color.float32[1] = 0.25;
4275             colorClearValue.color.float32[2] = 0.25;
4276             colorClearValue.color.float32[3] = 1.0f;
4277         }
4278         else
4279         {
4280             colorClearValue.color.float32[0] = 0.0f;
4281             colorClearValue.color.float32[1] = 0.0f;
4282             colorClearValue.color.float32[2] = 0.0f;
4283             colorClearValue.color.float32[3] = 0.0f;
4284         }
4285 
4286         VkClearValue depthStencilClearValue;
4287         depthStencilClearValue.depthStencil.depth   = m_depthClearValue;
4288         depthStencilClearValue.depthStencil.stencil = 0u;
4289 
4290         std::vector<VkClearValue> clearValues;
4291         clearValues.push_back(colorClearValue);
4292         if (usesResolveImage)
4293         {
4294             clearValues.push_back(colorClearValue);
4295         }
4296         if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4297         {
4298             for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4299             {
4300                 clearValues.push_back(colorClearValue);
4301             }
4302         }
4303         if (m_useDepth || m_useStencil)
4304         {
4305             clearValues.push_back(depthStencilClearValue);
4306         }
4307 
4308         vk::VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
4309         std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
4310 
4311         {
4312             const VkImageMemoryBarrier colorImageBarrier =
4313                 // color attachment image
4314                 {
4315                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,      // VkStructureType sType;
4316                     DE_NULL,                                     // const void* pNext;
4317                     0u,                                          // VkAccessFlags srcAccessMask;
4318                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,        // VkAccessFlags dstAccessMask;
4319                     VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout oldLayout;
4320                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout newLayout;
4321                     VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
4322                     VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
4323                     *m_colorImage,                               // VkImage image;
4324                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
4325                 };
4326             imageLayoutBarriers.push_back(colorImageBarrier);
4327         }
4328         if (usesResolveImage)
4329         {
4330             const VkImageMemoryBarrier resolveImageBarrier =
4331                 // resolve attachment image
4332                 {
4333                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,      // VkStructureType sType;
4334                     DE_NULL,                                     // const void* pNext;
4335                     0u,                                          // VkAccessFlags srcAccessMask;
4336                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,        // VkAccessFlags dstAccessMask;
4337                     VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout oldLayout;
4338                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout newLayout;
4339                     VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
4340                     VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
4341                     *m_resolveImage,                             // VkImage image;
4342                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
4343                 };
4344             imageLayoutBarriers.push_back(resolveImageBarrier);
4345         }
4346         if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4347         {
4348             for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4349             {
4350                 const VkImageMemoryBarrier perSampleImageBarrier =
4351                     // resolve attachment image
4352                     {
4353                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,      // VkStructureType sType;
4354                         DE_NULL,                                     // const void* pNext;
4355                         0u,                                          // VkAccessFlags srcAccessMask;
4356                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,        // VkAccessFlags dstAccessMask;
4357                         VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout oldLayout;
4358                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout newLayout;
4359                         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
4360                         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
4361                         *m_perSampleImages[i]->m_image,              // VkImage image;
4362                         {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
4363                     };
4364                 imageLayoutBarriers.push_back(perSampleImageBarrier);
4365             }
4366         }
4367         if (m_useDepth || m_useStencil)
4368         {
4369             const VkImageMemoryBarrier depthStencilImageBarrier =
4370                 // depth/stencil attachment image
4371                 {
4372                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,           // VkStructureType sType;
4373                     DE_NULL,                                          // const void* pNext;
4374                     0u,                                               // VkAccessFlags srcAccessMask;
4375                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,     // VkAccessFlags dstAccessMask;
4376                     VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout oldLayout;
4377                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
4378                     VK_QUEUE_FAMILY_IGNORED,                          // uint32_t srcQueueFamilyIndex;
4379                     VK_QUEUE_FAMILY_IGNORED,                          // uint32_t dstQueueFamilyIndex;
4380                     *m_depthStencilImage,                             // VkImage image;
4381                     {depthStencilAttachmentAspect, 0u, 1u, 0u, 1u},   // VkImageSubresourceRange subresourceRange;
4382                 };
4383             imageLayoutBarriers.push_back(depthStencilImageBarrier);
4384             dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
4385         }
4386 
4387         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4388 
4389         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
4390 
4391         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask, (VkDependencyFlags)0, 0u,
4392                               DE_NULL, 0u, DE_NULL, (uint32_t)imageLayoutBarriers.size(), &imageLayoutBarriers[0]);
4393 
4394         m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
4395                            (uint32_t)clearValues.size(), &clearValues[0]);
4396 
4397         VkDeviceSize vertexBufferOffset = 0u;
4398 
4399         for (uint32_t i = 0u; i < numTopologies; ++i)
4400         {
4401             m_graphicsPipelines[i].bind(*m_cmdBuffer);
4402             vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
4403             vk.cmdDraw(*m_cmdBuffer, (uint32_t)pVertices[i].size(), 1, 0, 0);
4404 
4405             vertexBufferOffset += static_cast<VkDeviceSize>(pVertices[i].size() * sizeof(Vertex4RGBA));
4406         }
4407 
4408         if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4409         {
4410             // The first draw was without color buffer and zero coverage. The depth buffer is expected to still have the clear value.
4411             m_renderPass.nextSubpass(vk, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
4412             m_graphicsPipelines[1].bind(*m_cmdBuffer);
4413             vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
4414             // The depth test should pass as the first draw didn't touch the depth buffer.
4415             vk.cmdDraw(*m_cmdBuffer, (uint32_t)pVertices[0].size(), 1, 0, 0);
4416         }
4417         else if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4418         {
4419             // Copy each sample id to single sampled image
4420             for (int32_t sampleId = 0; sampleId < (int32_t)m_perSampleImages.size(); ++sampleId)
4421             {
4422                 m_renderPass.nextSubpass(vk, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
4423                 m_copySamplePipelines[sampleId].bind(*m_cmdBuffer);
4424                 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_copySamplePipelineLayout, 0u,
4425                                          1u, &m_copySampleDesciptorSet.get(), 0u, DE_NULL);
4426                 vk.cmdPushConstants(*m_cmdBuffer, *m_copySamplePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4427                                     sizeof(int32_t), &sampleId);
4428                 vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
4429             }
4430         }
4431 
4432         m_renderPass.end(vk, *m_cmdBuffer);
4433 
4434         endCommandBuffer(vk, *m_cmdBuffer);
4435     }
4436 }
4437 
~MultisampleRenderer(void)4438 MultisampleRenderer::~MultisampleRenderer(void)
4439 {
4440 }
4441 
render(void)4442 de::MovePtr<tcu::TextureLevel> MultisampleRenderer::render(void)
4443 {
4444     const DeviceInterface &vk       = m_context.getDeviceInterface();
4445     const VkDevice vkDevice         = m_context.getDevice();
4446     const VkQueue queue             = m_context.getUniversalQueue();
4447     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4448 
4449     if (m_backingMode == IMAGE_BACKING_MODE_SPARSE)
4450     {
4451         const VkPipelineStageFlags stageBits[] = {VK_PIPELINE_STAGE_TRANSFER_BIT};
4452         submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get(), false, 1u, 1u, &m_bindSemaphore.get(), stageBits);
4453     }
4454     else
4455     {
4456         submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
4457     }
4458 
4459     if (m_renderType == RENDER_TYPE_RESOLVE || m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY ||
4460         m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT)
4461     {
4462         return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, m_context.getDefaultAllocator(),
4463                                    *m_resolveImage, m_colorFormat, m_renderSize.cast<uint32_t>());
4464     }
4465     else if (m_renderType == RENDER_TYPE_SINGLE_SAMPLE)
4466     {
4467         return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, m_context.getDefaultAllocator(),
4468                                    *m_colorImage, m_colorFormat, m_renderSize.cast<uint32_t>());
4469     }
4470     else
4471     {
4472         return de::MovePtr<tcu::TextureLevel>();
4473     }
4474 }
4475 
getSingleSampledImage(uint32_t sampleId)4476 de::MovePtr<tcu::TextureLevel> MultisampleRenderer::getSingleSampledImage(uint32_t sampleId)
4477 {
4478     return readColorAttachment(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
4479                                m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(),
4480                                *m_perSampleImages[sampleId]->m_image, m_colorFormat, m_renderSize.cast<uint32_t>());
4481 }
4482 
renderReusingDepth()4483 de::MovePtr<tcu::TextureLevel> MultisampleRenderer::renderReusingDepth()
4484 {
4485     const auto ctx          = m_context.getContextCommonData();
4486     const auto renderSize   = m_renderSize.cast<uint32_t>();
4487     const auto scissor      = makeRect2D(renderSize);
4488     const auto fbExtent     = makeExtent3D(scissor.extent.width, scissor.extent.height, 1u);
4489     const auto colorUsage   = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
4490     const auto sampleCount  = m_multisampleStateParams.rasterizationSamples;
4491     const auto singleSample = VK_SAMPLE_COUNT_1_BIT;
4492     const auto bindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
4493 
4494     ImageWithBuffer secondColorBuffer(ctx.vkd, ctx.device, ctx.allocator, fbExtent, m_colorFormat, colorUsage,
4495                                       VK_IMAGE_TYPE_2D, makeDefaultImageSubresourceRange(), 1u, sampleCount);
4496     ImageWithBuffer secondResolveBuffer(ctx.vkd, ctx.device, ctx.allocator, fbExtent, m_colorFormat, colorUsage,
4497                                         VK_IMAGE_TYPE_2D, makeDefaultImageSubresourceRange(), 1u, singleSample);
4498 
4499     const auto pcSize         = static_cast<uint32_t>(sizeof(float));
4500     const auto pcStages       = VK_SHADER_STAGE_VERTEX_BIT;
4501     const auto pcRange        = makePushConstantRange(pcStages, 0u, pcSize);
4502     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
4503 
4504     const std::vector<VkAttachmentDescription> attachmentDescriptions{
4505         {
4506             // Color attachment.
4507             0u,                                       // VkAttachmentDescriptionFlags flags;
4508             m_colorFormat,                            // VkFormat format;
4509             sampleCount,                              // VkSampleCountFlagBits samples;
4510             VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
4511             VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp storeOp;
4512             VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
4513             VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
4514             VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
4515             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
4516         },
4517         {
4518             // Depth/stencil attachment.
4519             0u,                                               // VkAttachmentDescriptionFlags flags;
4520             m_depthStencilFormat,                             // VkFormat format;
4521             sampleCount,                                      // VkSampleCountFlagBits samples;
4522             VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp loadOp;
4523             VK_ATTACHMENT_STORE_OP_DONT_CARE,                 // VkAttachmentStoreOp storeOp;
4524             VK_ATTACHMENT_LOAD_OP_DONT_CARE,                  // VkAttachmentLoadOp stencilLoadOp;
4525             VK_ATTACHMENT_STORE_OP_DONT_CARE,                 // VkAttachmentStoreOp stencilStoreOp;
4526             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
4527             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
4528         },
4529         {
4530             // Resolve attachment.
4531             0u,                                       // VkAttachmentDescriptionFlags flags;
4532             m_colorFormat,                            // VkFormat format;
4533             singleSample,                             // VkSampleCountFlagBits samples;
4534             VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp loadOp;
4535             VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
4536             VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
4537             VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
4538             VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
4539             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
4540         },
4541     };
4542 
4543     const auto colorAttachmentReference = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
4544     const auto dsAttachmentReference    = makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
4545     const auto resolveAttachmentReference = makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
4546 
4547     const VkSubpassDescription subpassDescription = {
4548         0u,                          // VkSubpassDescriptionFlags flags;
4549         bindPoint,                   // VkPipelineBindPoint pipelineBindPoint;
4550         0u,                          // uint32_t inputAttachmentCount;
4551         nullptr,                     // const VkAttachmentReference* pInputAttachments;
4552         1u,                          // uint32_t colorAttachmentCount;
4553         &colorAttachmentReference,   // const VkAttachmentReference* pColorAttachments;
4554         &resolveAttachmentReference, // const VkAttachmentReference* pResolveAttachments;
4555         &dsAttachmentReference,      // const VkAttachmentReference* pDepthStencilAttachment;
4556         0u,                          // uint32_t preserveAttachmentCount;
4557         nullptr,                     // const uint32_t* pPreserveAttachments;
4558     };
4559 
4560     const VkRenderPassCreateInfo rpCreateInfo = {
4561         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
4562         nullptr,                                   // const void* pNext;
4563         0u,                                        // VkRenderPassCreateFlags flags;
4564         de::sizeU32(attachmentDescriptions),       // uint32_t attachmentCount;
4565         de::dataOrNull(attachmentDescriptions),    // const VkAttachmentDescription* pAttachments;
4566         1u,                                        // uint32_t subpassCount;
4567         &subpassDescription,                       // const VkSubpassDescription* pSubpasses;
4568         0u,                                        // uint32_t dependencyCount;
4569         nullptr,                                   // const VkSubpassDependency* pDependencies;
4570     };
4571     const auto renderPass = createRenderPass(ctx.vkd, ctx.device, &rpCreateInfo);
4572 
4573     const std::vector<VkImageView> fbImageViews{
4574         secondColorBuffer.getImageView(),
4575         *m_depthStencilAttachmentView,
4576         secondResolveBuffer.getImageView(),
4577     };
4578     const auto framebuffer = makeFramebuffer(ctx.vkd, ctx.device, renderPass.get(), de::sizeU32(fbImageViews),
4579                                              de::dataOrNull(fbImageViews), fbExtent.width, fbExtent.height);
4580 
4581     const std::vector<VkViewport> viewports(1u, makeViewport(fbExtent));
4582     const std::vector<VkRect2D> scissors(1u, scissor);
4583     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
4584     const auto stencilOpState =
4585         makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0u, 0u, 0u);
4586 
4587     // This is the key to test the depth buffer contains the clear value and has not been written to:
4588     // The comparison op is EQUAL, so we will only draw if the depth buffer contains the expected value.
4589     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
4590         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
4591         nullptr,                                                    // const void* pNext;
4592         0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
4593         VK_TRUE,                                                    // VkBool32 depthTestEnable;
4594         VK_FALSE,                                                   // VkBool32 depthWriteEnable;
4595         VK_COMPARE_OP_EQUAL,                                        // VkCompareOp depthCompareOp;
4596         VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
4597         VK_FALSE,                                                   // VkBool32 stencilTestEnable;
4598         stencilOpState,                                             // VkStencilOpState front;
4599         stencilOpState,                                             // VkStencilOpState back;
4600         0.0f,                                                       // float minDepthBounds;
4601         1.0f,                                                       // float maxDepthBounds;
4602     };
4603 
4604     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
4605         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
4606         nullptr,                                                  // const void* pNext;
4607         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
4608         sampleCount,                                              // VkSampleCountFlagBits rasterizationSamples;
4609         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
4610         1.0f,                                                     // float minSampleShading;
4611         nullptr,                                                  // const VkSampleMask* pSampleMask;
4612         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
4613         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
4614     };
4615 
4616     const auto &binaries  = m_context.getBinaryCollection();
4617     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("checkDepth-vert"));
4618     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("color_frag"));
4619     const auto pipeline   = makeGraphicsPipeline(
4620         ctx.vkd, ctx.device, pipelineLayout.get(), vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
4621         fragModule.get(), renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
4622         &vertexInputStateCreateInfo, nullptr, &multisampleStateCreateInfo, &depthStencilStateCreateInfo);
4623 
4624     const CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
4625     const auto cmdBuffer = cmd.cmdBuffer.get();
4626     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
4627 
4628     beginCommandBuffer(ctx.vkd, cmdBuffer);
4629     {
4630         // Make sure the previous depth buffer writes have completed already.
4631         const auto depthBarrier = makeMemoryBarrier(
4632             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
4633             (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT));
4634         const auto depthStages =
4635             (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
4636         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, depthStages, depthStages, &depthBarrier);
4637     }
4638     beginRenderPass(ctx.vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissor, clearColor);
4639     ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipeline.get());
4640     ctx.vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &m_depthClearValue);
4641     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
4642     endRenderPass(ctx.vkd, cmdBuffer);
4643     endCommandBuffer(ctx.vkd, cmdBuffer);
4644     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
4645 
4646     return readColorAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator,
4647                                secondResolveBuffer.getImage(), m_colorFormat, renderSize);
4648 }
4649 
4650 // Multisample tests with subpasses using no attachments.
4651 class VariableRateTestCase : public vkt::TestCase
4652 {
4653 public:
4654     using SampleCounts = std::vector<vk::VkSampleCountFlagBits>;
4655 
4656     struct PushConstants
4657     {
4658         int width;
4659         int height;
4660         int samples;
4661     };
4662 
4663     struct TestParams
4664     {
4665         PipelineConstructionType pipelineConstructionType; // The way pipeline is constructed.
4666         bool nonEmptyFramebuffer;                          // Empty framebuffer or not.
4667         vk::VkSampleCountFlagBits fbCount;                 // If not empty, framebuffer sample count.
4668         bool unusedAttachment;                             // If not empty, create unused attachment or not.
4669         SampleCounts subpassCounts;                        // Counts for the different subpasses.
4670         bool useFragmentShadingRate;                       // Use pipeline fragment shading rate.
4671     };
4672 
4673     static const int32_t kWidth  = 256u;
4674     static const int32_t kHeight = 256u;
4675 
4676     VariableRateTestCase(tcu::TestContext &testCtx, const std::string &name, const TestParams &params);
~VariableRateTestCase(void)4677     virtual ~VariableRateTestCase(void)
4678     {
4679     }
4680 
4681     virtual void initPrograms(vk::SourceCollections &programCollection) const;
4682     virtual TestInstance *createInstance(Context &context) const;
4683     virtual void checkSupport(Context &context) const;
4684 
4685     static constexpr vk::VkFormat kColorFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
4686 
4687 private:
4688     TestParams m_params;
4689 };
4690 
4691 class VariableRateTestInstance : public vkt::TestInstance
4692 {
4693 public:
4694     using TestParams = VariableRateTestCase::TestParams;
4695 
4696     VariableRateTestInstance(Context &context, const TestParams &counts);
~VariableRateTestInstance(void)4697     virtual ~VariableRateTestInstance(void)
4698     {
4699     }
4700 
4701     virtual tcu::TestStatus iterate(void);
4702 
4703 private:
4704     TestParams m_params;
4705 };
4706 
VariableRateTestCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)4707 VariableRateTestCase::VariableRateTestCase(tcu::TestContext &testCtx, const std::string &name, const TestParams &params)
4708     : vkt::TestCase(testCtx, name)
4709     , m_params(params)
4710 {
4711 }
4712 
initPrograms(vk::SourceCollections & programCollection) const4713 void VariableRateTestCase::initPrograms(vk::SourceCollections &programCollection) const
4714 {
4715     std::stringstream vertSrc;
4716 
4717     vertSrc << "#version 450\n"
4718             << "\n"
4719             << "layout(location=0) in vec2 inPos;\n"
4720             << "\n"
4721             << "void main() {\n"
4722             << "    gl_Position = vec4(inPos, 0.0, 1.0);\n"
4723             << "}\n";
4724 
4725     std::stringstream fragSrc;
4726 
4727     fragSrc
4728         << "#version 450\n"
4729         << "\n"
4730         << "layout(set=0, binding=0, std430) buffer OutBuffer {\n"
4731         << "    int coverage[];\n"
4732         << "} out_buffer;\n"
4733         << "\n"
4734         << "layout(push_constant) uniform PushConstants {\n"
4735         << "    int width;\n"
4736         << "    int height;\n"
4737         << "    int samples;\n"
4738         << "} push_constants;\n"
4739         << "\n"
4740         << "void main() {\n"
4741         << "   ivec2 coord = ivec2(floor(gl_FragCoord.xy));\n"
4742         << "   int pos = ((coord.y * push_constants.width) + coord.x) * push_constants.samples + int(gl_SampleID);\n"
4743         << "   out_buffer.coverage[pos] = 1;\n"
4744         << "}\n";
4745 
4746     programCollection.glslSources.add("vert") << glu::VertexSource(vertSrc.str());
4747     programCollection.glslSources.add("frag") << glu::FragmentSource(fragSrc.str());
4748 }
4749 
createInstance(Context & context) const4750 TestInstance *VariableRateTestCase::createInstance(Context &context) const
4751 {
4752     return new VariableRateTestInstance(context, m_params);
4753 }
4754 
checkSupport(Context & context) const4755 void VariableRateTestCase::checkSupport(Context &context) const
4756 {
4757     const auto &vki           = context.getInstanceInterface();
4758     const auto physicalDevice = context.getPhysicalDevice();
4759 
4760     // When using multiple subpasses, require variableMultisampleRate.
4761     if (m_params.subpassCounts.size() > 1)
4762     {
4763         if (!vk::getPhysicalDeviceFeatures(vki, physicalDevice).variableMultisampleRate)
4764             TCU_THROW(NotSupportedError, "Variable multisample rate not supported");
4765     }
4766 
4767     // Check if sampleRateShading is supported.
4768     if (!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading)
4769         TCU_THROW(NotSupportedError, "Sample rate shading is not supported");
4770 
4771     // Make sure all subpass sample counts are supported.
4772     const auto properties       = vk::getPhysicalDeviceProperties(vki, physicalDevice);
4773     const auto &supportedCounts = properties.limits.framebufferNoAttachmentsSampleCounts;
4774 
4775     for (const auto count : m_params.subpassCounts)
4776     {
4777         if ((supportedCounts & count) == 0u)
4778             TCU_THROW(NotSupportedError, "Sample count combination not supported");
4779     }
4780 
4781     if (m_params.nonEmptyFramebuffer)
4782     {
4783         // Check the framebuffer sample count is supported.
4784         const auto formatProperties = vk::getPhysicalDeviceImageFormatProperties(
4785             vki, physicalDevice, kColorFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL,
4786             vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0u);
4787         if ((formatProperties.sampleCounts & m_params.fbCount) == 0u)
4788             TCU_THROW(NotSupportedError,
4789                       "Sample count of " + de::toString(m_params.fbCount) + " not supported for color attachment");
4790     }
4791 
4792     if (m_params.useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, m_params.fbCount))
4793         TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
4794 
4795     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
4796                                           m_params.pipelineConstructionType);
4797 }
4798 
zeroOutAndFlush(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::BufferWithMemory & buffer,vk::VkDeviceSize size)4799 void zeroOutAndFlush(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::BufferWithMemory &buffer,
4800                      vk::VkDeviceSize size)
4801 {
4802     auto &alloc = buffer.getAllocation();
4803     deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(size));
4804     vk::flushAlloc(vkd, device, alloc);
4805 }
4806 
VariableRateTestInstance(Context & context,const TestParams & params)4807 VariableRateTestInstance::VariableRateTestInstance(Context &context, const TestParams &params)
4808     : vkt::TestInstance(context)
4809     , m_params(params)
4810 {
4811 }
4812 
iterate(void)4813 tcu::TestStatus VariableRateTestInstance::iterate(void)
4814 {
4815     using PushConstants = VariableRateTestCase::PushConstants;
4816 
4817     const auto &vki       = m_context.getInstanceInterface();
4818     const auto &vkd       = m_context.getDeviceInterface();
4819     const auto physDevice = m_context.getPhysicalDevice();
4820     const auto device     = m_context.getDevice();
4821     auto &allocator       = m_context.getDefaultAllocator();
4822     const auto &queue     = m_context.getUniversalQueue();
4823     const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
4824 
4825     const vk::VkDeviceSize kWidth  = static_cast<vk::VkDeviceSize>(VariableRateTestCase::kWidth);
4826     const vk::VkDeviceSize kHeight = static_cast<vk::VkDeviceSize>(VariableRateTestCase::kHeight);
4827     constexpr auto kColorFormat    = VariableRateTestCase::kColorFormat;
4828 
4829     const auto kWidth32  = static_cast<uint32_t>(kWidth);
4830     const auto kHeight32 = static_cast<uint32_t>(kHeight);
4831 
4832     std::vector<std::unique_ptr<vk::BufferWithMemory>> referenceBuffers;
4833     std::vector<std::unique_ptr<vk::BufferWithMemory>> outputBuffers;
4834     std::vector<size_t> bufferNumElements;
4835     std::vector<vk::VkDeviceSize> bufferSizes;
4836 
4837     // Create reference and output buffers.
4838     for (const auto count : m_params.subpassCounts)
4839     {
4840         bufferNumElements.push_back(static_cast<size_t>(kWidth * kHeight * count));
4841         bufferSizes.push_back(bufferNumElements.back() * sizeof(int32_t));
4842         const auto bufferCreateInfo =
4843             vk::makeBufferCreateInfo(bufferSizes.back(), vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
4844 
4845         referenceBuffers.emplace_back(
4846             new vk::BufferWithMemory{vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible});
4847         outputBuffers.emplace_back(
4848             new vk::BufferWithMemory{vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible});
4849     }
4850 
4851     // Descriptor set layout.
4852     vk::DescriptorSetLayoutBuilder builder;
4853     builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
4854     const auto descriptorSetLayout = builder.build(vkd, device);
4855 
4856     // Pipeline layout.
4857     const vk::VkPushConstantRange pushConstantRange = {
4858         vk::VK_SHADER_STAGE_FRAGMENT_BIT,             // VkShaderStageFlags stageFlags;
4859         0u,                                           // uint32_t offset;
4860         static_cast<uint32_t>(sizeof(PushConstants)), // uint32_t size;
4861     };
4862 
4863     const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
4864         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
4865         nullptr,                                           // const void* pNext;
4866         0u,                                                // VkPipelineLayoutCreateFlags flags;
4867         1u,                                                // uint32_t setLayoutCount;
4868         &descriptorSetLayout.get(),                        // const VkDescriptorSetLayout* pSetLayouts;
4869         1u,                                                // uint32_t pushConstantRangeCount;
4870         &pushConstantRange,                                // const VkPushConstantRange* pPushConstantRanges;
4871     };
4872     const vk::PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, vkd, device,
4873                                                    &pipelineLayoutCreateInfo);
4874 
4875     // Subpass with no attachments.
4876     const vk::VkSubpassDescription emptySubpassDescription = {
4877         0u,                                  // VkSubpassDescriptionFlags flags;
4878         vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
4879         0u,                                  // uint32_t inputAttachmentCount;
4880         nullptr,                             // const VkAttachmentReference* pInputAttachments;
4881         0u,                                  // uint32_t colorAttachmentCount;
4882         nullptr,                             // const VkAttachmentReference* pColorAttachments;
4883         nullptr,                             // const VkAttachmentReference* pResolveAttachments;
4884         nullptr,                             // const VkAttachmentReference* pDepthStencilAttachment;
4885         0u,                                  // uint32_t preserveAttachmentCount;
4886         nullptr,                             // const uint32_t* pPreserveAttachments;
4887     };
4888 
4889     // Unused attachment reference.
4890     const vk::VkAttachmentReference unusedAttachmentReference = {
4891         VK_ATTACHMENT_UNUSED,                         // uint32_t attachment;
4892         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
4893     };
4894 
4895     // Subpass with unused attachment.
4896     const vk::VkSubpassDescription unusedAttachmentSubpassDescription = {
4897         0u,                                  // VkSubpassDescriptionFlags flags;
4898         vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
4899         0u,                                  // uint32_t inputAttachmentCount;
4900         nullptr,                             // const VkAttachmentReference* pInputAttachments;
4901         1u,                                  // uint32_t colorAttachmentCount;
4902         &unusedAttachmentReference,          // const VkAttachmentReference* pColorAttachments;
4903         nullptr,                             // const VkAttachmentReference* pResolveAttachments;
4904         nullptr,                             // const VkAttachmentReference* pDepthStencilAttachment;
4905         0u,                                  // uint32_t preserveAttachmentCount;
4906         nullptr,                             // const uint32_t* pPreserveAttachments;
4907     };
4908 
4909     // Renderpass with multiple subpasses.
4910     vk::VkRenderPassCreateInfo renderPassCreateInfo = {
4911         vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
4912         nullptr,                                       // const void* pNext;
4913         0u,                                            // VkRenderPassCreateFlags flags;
4914         0u,                                            // uint32_t attachmentCount;
4915         nullptr,                                       // const VkAttachmentDescription* pAttachments;
4916         0u,                                            // uint32_t subpassCount;
4917         nullptr,                                       // const VkSubpassDescription* pSubpasses;
4918         0u,                                            // uint32_t dependencyCount;
4919         nullptr,                                       // const VkSubpassDependency* pDependencies;
4920     };
4921 
4922     std::vector<vk::VkSubpassDescription> subpassesVector;
4923 
4924     for (size_t i = 0; i < m_params.subpassCounts.size(); ++i)
4925         subpassesVector.push_back(emptySubpassDescription);
4926     renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassesVector.size());
4927     renderPassCreateInfo.pSubpasses   = subpassesVector.data();
4928     RenderPassWrapper renderPassMultiplePasses(m_params.pipelineConstructionType, vkd, device, &renderPassCreateInfo);
4929 
4930     // Render pass with single subpass.
4931     const vk::VkAttachmentDescription colorAttachmentDescription = {
4932         0u,                                           // VkAttachmentDescriptionFlags flags;
4933         kColorFormat,                                 // VkFormat format;
4934         m_params.fbCount,                             // VkSampleCountFlagBits samples;
4935         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp loadOp;
4936         vk::VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
4937         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
4938         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
4939         vk::VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
4940         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
4941     };
4942 
4943     if (m_params.nonEmptyFramebuffer)
4944     {
4945         renderPassCreateInfo.attachmentCount = 1u;
4946         renderPassCreateInfo.pAttachments    = &colorAttachmentDescription;
4947     }
4948     const bool unusedAttachmentSubpass = (m_params.nonEmptyFramebuffer && m_params.unusedAttachment);
4949     renderPassCreateInfo.subpassCount  = 1u;
4950     renderPassCreateInfo.pSubpasses =
4951         (unusedAttachmentSubpass ? &unusedAttachmentSubpassDescription : &emptySubpassDescription);
4952     RenderPassWrapper renderPassSingleSubpass(m_params.pipelineConstructionType, vkd, device, &renderPassCreateInfo);
4953 
4954     // Framebuffers.
4955     vk::VkFramebufferCreateInfo framebufferCreateInfo = {
4956         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
4957         nullptr,                                       // const void* pNext;
4958         0u,                                            // VkFramebufferCreateFlags flags;
4959         DE_NULL,                                       // VkRenderPass renderPass;
4960         0u,                                            // uint32_t attachmentCount;
4961         nullptr,                                       // const VkImageView* pAttachments;
4962         kWidth32,                                      // uint32_t width;
4963         kHeight32,                                     // uint32_t height;
4964         1u,                                            // uint32_t layers;
4965     };
4966 
4967     // Framebuffer for multiple-subpasses render pass.
4968     framebufferCreateInfo.renderPass = renderPassMultiplePasses.get();
4969     renderPassMultiplePasses.createFramebuffer(vkd, device, &framebufferCreateInfo, std::vector<VkImage>{});
4970 
4971     // Framebuffer for single-subpass render pass.
4972     std::unique_ptr<vk::ImageWithMemory> imagePtr;
4973     vk::Move<vk::VkImageView> imageView;
4974     std::vector<vk::VkImage> images;
4975 
4976     if (m_params.nonEmptyFramebuffer)
4977     {
4978         const vk::VkImageCreateInfo imageCreateInfo = {
4979             vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,   // VkStructureType sType;
4980             nullptr,                                   // const void* pNext;
4981             0u,                                        // VkImageCreateFlags flags;
4982             vk::VK_IMAGE_TYPE_2D,                      // VkImageType imageType;
4983             kColorFormat,                              // VkFormat format;
4984             vk::makeExtent3D(kWidth32, kHeight32, 1u), // VkExtent3D extent;
4985             1u,                                        // uint32_t mipLevels;
4986             1u,                                        // uint32_t arrayLayers;
4987             m_params.fbCount,                          // VkSampleCountFlagBits samples;
4988             vk::VK_IMAGE_TILING_OPTIMAL,               // VkImageTiling tiling;
4989             vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,   // VkImageUsageFlags usage;
4990             vk::VK_SHARING_MODE_EXCLUSIVE,             // VkSharingMode sharingMode;
4991             0u,                                        // uint32_t queueFamilyIndexCount;
4992             nullptr,                                   // const uint32_t* pQueueFamilyIndices;
4993             vk::VK_IMAGE_LAYOUT_UNDEFINED,             // VkImageLayout initialLayout;
4994         };
4995         imagePtr.reset(new vk::ImageWithMemory{vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any});
4996 
4997         const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4998         imageView =
4999             vk::makeImageView(vkd, device, imagePtr->get(), vk::VK_IMAGE_VIEW_TYPE_2D, kColorFormat, subresourceRange);
5000 
5001         framebufferCreateInfo.attachmentCount = 1u;
5002         framebufferCreateInfo.pAttachments    = &imageView.get();
5003         images.push_back(**imagePtr);
5004     }
5005     framebufferCreateInfo.renderPass = renderPassSingleSubpass.get();
5006     renderPassSingleSubpass.createFramebuffer(vkd, device, &framebufferCreateInfo, images);
5007 
5008     // Shader modules and stages.
5009     const auto vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
5010     const auto fragModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
5011 
5012     // Vertices, input state and assembly.
5013     const std::vector<tcu::Vec2> vertices = {
5014         {-0.987f, -0.964f},
5015         {0.982f, -0.977f},
5016         {0.005f, 0.891f},
5017     };
5018 
5019     const auto vertexBinding = vk::makeVertexInputBindingDescription(
5020         0u, static_cast<uint32_t>(sizeof(decltype(vertices)::value_type)), vk::VK_VERTEX_INPUT_RATE_VERTEX);
5021     const auto vertexAttribute = vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u);
5022 
5023     const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
5024         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
5025         nullptr,                                                       // const void* pNext;
5026         0u,                                                            // VkPipelineVertexInputStateCreateFlags flags;
5027         1u,                                                            // uint32_t vertexBindingDescriptionCount;
5028         &vertexBinding,   // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
5029         1u,               // uint32_t vertexAttributeDescriptionCount;
5030         &vertexAttribute, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
5031     };
5032 
5033     // Graphics pipelines to create output buffers.
5034     const std::vector<VkViewport> viewport{vk::makeViewport(kWidth32, kHeight32)};
5035     const std::vector<VkRect2D> scissor{vk::makeRect2D(kWidth32, kHeight32)};
5036 
5037     const VkColorComponentFlags colorComponentFlags =
5038         (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
5039 
5040     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
5041         VK_FALSE,             // VkBool32 blendEnable;
5042         VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
5043         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
5044         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
5045         VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
5046         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
5047         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
5048         colorComponentFlags,  // VkColorComponentFlags colorWriteMask;
5049     };
5050 
5051     const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoNoAttachments = {
5052         vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
5053         DE_NULL,                                                      // const void* pNext;
5054         0u,                                                           // VkPipelineColorBlendStateCreateFlags flags;
5055         VK_FALSE,                                                     // VkBool32 logicOpEnable;
5056         vk::VK_LOGIC_OP_CLEAR,                                        // VkLogicOp logicOp;
5057         0u,                                                           // uint32_t attachmentCount;
5058         nullptr,                 // const VkPipelineColorBlendAttachmentState* pAttachments;
5059         {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
5060     };
5061 
5062     const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoOneAttachment = {
5063         vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
5064         DE_NULL,                                                      // const void* pNext;
5065         0u,                                                           // VkPipelineColorBlendStateCreateFlags flags;
5066         VK_FALSE,                                                     // VkBool32 logicOpEnable;
5067         vk::VK_LOGIC_OP_CLEAR,                                        // VkLogicOp logicOp;
5068         1u,                                                           // uint32_t attachmentCount;
5069         &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
5070         {0.0f, 0.0f, 0.0f, 0.0f}    // float blendConstants[4];
5071     };
5072 
5073     vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo{
5074         vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
5075         nullptr,                                                      // const void* pNext;
5076         0u,                                                           // VkPipelineMultisampleStateCreateFlags flags;
5077         vk::VK_SAMPLE_COUNT_1_BIT,                                    // VkSampleCountFlagBits rasterizationSamples;
5078         VK_FALSE,                                                     // VkBool32 sampleShadingEnable;
5079         0.0f,                                                         // float minSampleShading;
5080         nullptr,                                                      // const VkSampleMask* pSampleMask;
5081         VK_FALSE,                                                     // VkBool32 alphaToCoverageEnable;
5082         VK_FALSE,                                                     // VkBool32 alphaToOneEnable;
5083     };
5084 
5085     std::vector<GraphicsPipelineWrapper> outputPipelines;
5086     outputPipelines.reserve(m_params.subpassCounts.size());
5087     for (const auto samples : m_params.subpassCounts)
5088     {
5089         const auto colorBlendStatePtr = (unusedAttachmentSubpass ? &colorBlendStateCreateInfoOneAttachment :
5090                                                                    &colorBlendStateCreateInfoNoAttachments);
5091 
5092         multisampleStateCreateInfo.rasterizationSamples = samples;
5093 
5094         outputPipelines.emplace_back(vki, vkd, physDevice, device, m_context.getDeviceExtensions(),
5095                                      m_params.pipelineConstructionType);
5096         outputPipelines.back()
5097             .setDefaultDepthStencilState()
5098             .setDefaultRasterizationState()
5099             .setupVertexInputState(&vertexInputStateCreateInfo)
5100             .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, *renderPassSingleSubpass, 0u,
5101                                               vertModule)
5102             .setupFragmentShaderState(pipelineLayout, *renderPassSingleSubpass, 0u, fragModule, DE_NULL,
5103                                       &multisampleStateCreateInfo)
5104             .setupFragmentOutputState(*renderPassSingleSubpass, 0u, colorBlendStatePtr, &multisampleStateCreateInfo)
5105             .setMonolithicPipelineLayout(pipelineLayout)
5106             .buildPipeline();
5107     }
5108 
5109     // Graphics pipelines with variable rate but using several subpasses.
5110     std::vector<GraphicsPipelineWrapper> referencePipelines;
5111     referencePipelines.reserve(m_params.subpassCounts.size());
5112     for (size_t i = 0; i < m_params.subpassCounts.size(); ++i)
5113     {
5114         multisampleStateCreateInfo.rasterizationSamples = m_params.subpassCounts[i];
5115 
5116         uint32_t subpass = static_cast<uint32_t>(i);
5117         referencePipelines.emplace_back(vki, vkd, physDevice, device, m_context.getDeviceExtensions(),
5118                                         m_params.pipelineConstructionType);
5119         referencePipelines.back()
5120             .setDefaultDepthStencilState()
5121             .setDefaultRasterizationState()
5122             .setupVertexInputState(&vertexInputStateCreateInfo)
5123             .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, *renderPassMultiplePasses, subpass,
5124                                               vertModule)
5125             .setupFragmentShaderState(pipelineLayout, *renderPassMultiplePasses, subpass, fragModule, DE_NULL,
5126                                       &multisampleStateCreateInfo)
5127             .setupFragmentOutputState(*renderPassMultiplePasses, subpass, &colorBlendStateCreateInfoNoAttachments,
5128                                       &multisampleStateCreateInfo)
5129             .setMonolithicPipelineLayout(pipelineLayout)
5130             .buildPipeline();
5131     }
5132 
5133     // Prepare vertex, reference and output buffers.
5134     const auto vertexBufferSize = vertices.size() * sizeof(decltype(vertices)::value_type);
5135     const auto vertexBufferCreateInfo =
5136         vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(vertexBufferSize), vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
5137     vk::BufferWithMemory vertexBuffer{vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible};
5138     auto &vertexAlloc = vertexBuffer.getAllocation();
5139 
5140     deMemcpy(vertexAlloc.getHostPtr(), vertices.data(), vertexBufferSize);
5141     vk::flushAlloc(vkd, device, vertexAlloc);
5142 
5143     for (size_t i = 0; i < referenceBuffers.size(); ++i)
5144     {
5145         zeroOutAndFlush(vkd, device, *referenceBuffers[i], bufferSizes[i]);
5146         zeroOutAndFlush(vkd, device, *outputBuffers[i], bufferSizes[i]);
5147     }
5148 
5149     // Prepare descriptor sets.
5150     const uint32_t totalSets = static_cast<uint32_t>(referenceBuffers.size() * 2u);
5151     vk::DescriptorPoolBuilder poolBuilder;
5152     poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast<uint32_t>(referenceBuffers.size() * 2u));
5153     const auto descriptorPool =
5154         poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, totalSets);
5155 
5156     std::vector<vk::Move<vk::VkDescriptorSet>> referenceSets(referenceBuffers.size());
5157     std::vector<vk::Move<vk::VkDescriptorSet>> outputSets(outputBuffers.size());
5158 
5159     for (auto &set : referenceSets)
5160         set = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
5161     for (auto &set : outputSets)
5162         set = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
5163 
5164     vk::DescriptorSetUpdateBuilder updateBuilder;
5165 
5166     for (size_t i = 0; i < referenceSets.size(); ++i)
5167     {
5168         const auto descriptorBufferInfo = vk::makeDescriptorBufferInfo(referenceBuffers[i]->get(), 0u, bufferSizes[i]);
5169         updateBuilder.writeSingle(referenceSets[i].get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u),
5170                                   vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
5171     }
5172     for (size_t i = 0; i < outputSets.size(); ++i)
5173     {
5174         const auto descriptorBufferInfo = vk::makeDescriptorBufferInfo(outputBuffers[i]->get(), 0u, bufferSizes[i]);
5175         updateBuilder.writeSingle(outputSets[i].get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u),
5176                                   vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
5177     }
5178 
5179     updateBuilder.update(vkd, device);
5180 
5181     // Prepare command pool.
5182     const auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
5183     const auto cmdBufferPtr =
5184         vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5185     const auto cmdBuffer = cmdBufferPtr.get();
5186 
5187     vk::VkBufferMemoryBarrier storageBufferDevToHostBarrier = {
5188         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
5189         nullptr,                                     // const void* pNext;
5190         vk::VK_ACCESS_SHADER_WRITE_BIT,              // VkAccessFlags srcAccessMask;
5191         vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
5192         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
5193         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
5194         DE_NULL,                                     // VkBuffer buffer;
5195         0u,                                          // VkDeviceSize offset;
5196         VK_WHOLE_SIZE,                               // VkDeviceSize size;
5197     };
5198 
5199     // Record command buffer.
5200     const vk::VkDeviceSize vertexBufferOffset = 0u;
5201     const auto renderArea                     = vk::makeRect2D(kWidth32, kHeight32);
5202     PushConstants pushConstants               = {static_cast<int>(kWidth), static_cast<int>(kHeight), 0};
5203 
5204     vk::beginCommandBuffer(vkd, cmdBuffer);
5205 
5206     // Render output buffers.
5207     renderPassSingleSubpass.begin(vkd, cmdBuffer, renderArea);
5208     for (size_t i = 0; i < outputBuffers.size(); ++i)
5209     {
5210         outputPipelines[i].bind(cmdBuffer);
5211         vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
5212                                   &outputSets[i].get(), 0u, nullptr);
5213         vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
5214         pushConstants.samples = static_cast<int>(m_params.subpassCounts[i]);
5215         vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantRange.stageFlags, pushConstantRange.offset,
5216                              pushConstantRange.size, &pushConstants);
5217         vkd.cmdDraw(cmdBuffer, static_cast<uint32_t>(vertices.size()), 1u, 0u, 0u);
5218     }
5219     renderPassSingleSubpass.end(vkd, cmdBuffer);
5220     for (size_t i = 0; i < outputBuffers.size(); ++i)
5221     {
5222         storageBufferDevToHostBarrier.buffer = outputBuffers[i]->get();
5223         vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u,
5224                                0u, nullptr, 1u, &storageBufferDevToHostBarrier, 0u, nullptr);
5225     }
5226 
5227     // Render reference buffers.
5228     renderPassMultiplePasses.begin(vkd, cmdBuffer, renderArea);
5229     for (size_t i = 0; i < referenceBuffers.size(); ++i)
5230     {
5231         if (i > 0)
5232             renderPassMultiplePasses.nextSubpass(vkd, cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
5233         referencePipelines[i].bind(cmdBuffer);
5234         vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
5235                                   &referenceSets[i].get(), 0u, nullptr);
5236         vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
5237         pushConstants.samples = static_cast<int>(m_params.subpassCounts[i]);
5238         vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantRange.stageFlags, pushConstantRange.offset,
5239                              pushConstantRange.size, &pushConstants);
5240         vkd.cmdDraw(cmdBuffer, static_cast<uint32_t>(vertices.size()), 1u, 0u, 0u);
5241     }
5242     renderPassMultiplePasses.end(vkd, cmdBuffer);
5243     for (size_t i = 0; i < referenceBuffers.size(); ++i)
5244     {
5245         storageBufferDevToHostBarrier.buffer = referenceBuffers[i]->get();
5246         vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u,
5247                                0u, nullptr, 1u, &storageBufferDevToHostBarrier, 0u, nullptr);
5248     }
5249 
5250     vk::endCommandBuffer(vkd, cmdBuffer);
5251 
5252     // Run all pipelines.
5253     vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
5254 
5255     // Invalidate reference allocs.
5256 #undef LOG_BUFFER_CONTENTS
5257 #ifdef LOG_BUFFER_CONTENTS
5258     auto &log = m_context.getTestContext().getLog();
5259 #endif
5260     for (size_t i = 0; i < referenceBuffers.size(); ++i)
5261     {
5262         auto &buffer = referenceBuffers[i];
5263         auto &alloc  = buffer->getAllocation();
5264         vk::invalidateAlloc(vkd, device, alloc);
5265 
5266 #ifdef LOG_BUFFER_CONTENTS
5267         std::vector<int32_t> bufferValues(bufferNumElements[i]);
5268         deMemcpy(bufferValues.data(), alloc.getHostPtr(), bufferSizes[i]);
5269 
5270         std::ostringstream msg;
5271         for (const auto value : bufferValues)
5272             msg << " " << value;
5273         log << tcu::TestLog::Message << "Reference buffer values with " << m_params[i] << " samples:" << msg.str()
5274             << tcu::TestLog::EndMessage;
5275 #endif
5276     }
5277 
5278     for (size_t i = 0; i < outputBuffers.size(); ++i)
5279     {
5280         auto &buffer = outputBuffers[i];
5281         auto &alloc  = buffer->getAllocation();
5282         vk::invalidateAlloc(vkd, device, alloc);
5283 
5284 #ifdef LOG_BUFFER_CONTENTS
5285         std::vector<int32_t> bufferValues(bufferNumElements[i]);
5286         deMemcpy(bufferValues.data(), alloc.getHostPtr(), bufferSizes[i]);
5287 
5288         std::ostringstream msg;
5289         for (const auto value : bufferValues)
5290             msg << " " << value;
5291         log << tcu::TestLog::Message << "Output buffer values with " << m_params[i] << " samples:" << msg.str()
5292             << tcu::TestLog::EndMessage;
5293 #endif
5294 
5295         if (deMemCmp(alloc.getHostPtr(), referenceBuffers[i]->getAllocation().getHostPtr(),
5296                      static_cast<size_t>(bufferSizes[i])) != 0)
5297             return tcu::TestStatus::fail("Buffer mismatch in output buffer " + de::toString(i));
5298     }
5299 
5300     return tcu::TestStatus::pass("Pass");
5301 }
5302 
5303 using ElementsVector    = std::vector<vk::VkSampleCountFlagBits>;
5304 using CombinationVector = std::vector<ElementsVector>;
5305 
combinationsRecursive(const ElementsVector & elements,size_t requestedSize,CombinationVector & solutions,ElementsVector & partial)5306 void combinationsRecursive(const ElementsVector &elements, size_t requestedSize, CombinationVector &solutions,
5307                            ElementsVector &partial)
5308 {
5309     if (partial.size() == requestedSize)
5310         solutions.push_back(partial);
5311     else
5312     {
5313         for (const auto &elem : elements)
5314         {
5315             partial.push_back(elem);
5316             combinationsRecursive(elements, requestedSize, solutions, partial);
5317             partial.pop_back();
5318         }
5319     }
5320 }
5321 
combinations(const ElementsVector & elements,size_t requestedSize)5322 CombinationVector combinations(const ElementsVector &elements, size_t requestedSize)
5323 {
5324     CombinationVector solutions;
5325     ElementsVector partial;
5326 
5327     combinationsRecursive(elements, requestedSize, solutions, partial);
5328     return solutions;
5329 }
5330 
5331 /********
5332 Z EXPORT TESTS
5333 
5334 The tests enable alpha to coverage statically or dynamically, and play with 3 other parameters, which we can be testing or not as
5335 outputs from the frag shader.
5336 
5337 * Depth value
5338 * Stencil reference value
5339 * Sample mask
5340 
5341 Alpha values on the left side of the framebuffer will be 0.0. On the right side they will be 1.0. This means the left side should
5342 not have coverage, and the right side should have.
5343 
5344 Depth value will be cleared to 1.0 and we expect to obtain 0.0 for covered pixels at the end. We will activate the depth test with a
5345 depth compare op of "less".
5346 
5347 * If we are testing this, we will set 0.5 from the vertex shader and 0.0 from the frag shader.
5348 * If we are not testing this, we will set 0.0 directly from the vertex shader.
5349 
5350 Stencil will be cleared to 0 and we expect to obtain 255 for covered pixels at the end. We will activate the stencil test with a
5351 stencil op of "replace" for front-facing pixels, compare op "always", keep and "never" for back-facing pixels.
5352 
5353 * If we are testing this, the stencil ref value will be 128 in the pipeline, then 255 from the frag shader.
5354 * If we are not testing this, the reference value will be set to 255 directly in the pipeline.
5355 
5356 Sample mask is a bit special: we'll always set it to 0xFF in the pipeline, and we normally expect all pixels to be covered.
5357 
5358 * If we are testing this, we'll set it to 0x00 on the lower half of the framebuffer.
5359 * If we are not testing this, we'll leave it as it is.
5360 
5361 Expected result:
5362 
5363 * The left side of the framebuffer will have:
5364   - The clear color.
5365   - The clear depth value.
5366   - The clear stencil value.
5367 
5368 * The right side of the framebuffer will have:
5369   - The geometry color (typically blue).
5370   - The expected depth value.
5371   - The expected stencil value.
5372   - But, if we are testing the sample mask, the lower half of the right side will be like the left side.
5373 
5374 ********/
5375 enum ZExportTestBits
5376 {
5377     ZEXP_DEPTH_BIT       = 0x1,
5378     ZEXP_STENCIL_BIT     = 0x2, // Requires VK_EXT_shader_stencil_export
5379     ZEXP_SAMPLE_MASK_BIT = 0x4,
5380 };
5381 
5382 using ZExportFlags = uint32_t;
5383 
5384 struct ZExportParams
5385 {
5386     const PipelineConstructionType pipelineConstructionType;
5387     const ZExportFlags testFlags;
5388     const bool dynamicAlphaToCoverage;
5389     const bool dynamicRendering;
5390 
ZExportParamsvkt::pipeline::__anon85754e250111::ZExportParams5391     ZExportParams(PipelineConstructionType pipelineConstructionType_, ZExportFlags testFlags_,
5392                   bool dynamicAlphaToCoverage_, bool dynamicRendering_)
5393         : pipelineConstructionType(pipelineConstructionType_)
5394         , testFlags(testFlags_)
5395         , dynamicAlphaToCoverage(dynamicAlphaToCoverage_)
5396         , dynamicRendering(dynamicRendering_)
5397     {
5398     }
5399 
testDepthvkt::pipeline::__anon85754e250111::ZExportParams5400     bool testDepth(void) const
5401     {
5402         return hasFlag(ZEXP_DEPTH_BIT);
5403     }
testStencilvkt::pipeline::__anon85754e250111::ZExportParams5404     bool testStencil(void) const
5405     {
5406         return hasFlag(ZEXP_STENCIL_BIT);
5407     }
testSampleMaskvkt::pipeline::__anon85754e250111::ZExportParams5408     bool testSampleMask(void) const
5409     {
5410         return hasFlag(ZEXP_SAMPLE_MASK_BIT);
5411     }
5412 
5413     static constexpr float kClearDepth    = 1.0f;
5414     static constexpr float kExpectedDepth = 0.0f;
5415     static constexpr float kBadDepth      = 0.5f;
5416 
5417     static constexpr uint32_t kClearStencil    = 0u;
5418     static constexpr uint32_t kExpectedStencil = 255u;
5419     static constexpr uint32_t kBadStencil      = 128u;
5420 
5421     static constexpr uint32_t kWidth  = 4u;
5422     static constexpr uint32_t kHeight = 4u;
5423 
5424 private:
hasFlagvkt::pipeline::__anon85754e250111::ZExportParams5425     bool hasFlag(ZExportTestBits bit) const
5426     {
5427         return ((testFlags & static_cast<ZExportFlags>(bit)) != 0u);
5428     }
5429 };
5430 
ZExportCheckSupport(Context & context,const ZExportParams params)5431 void ZExportCheckSupport(Context &context, const ZExportParams params)
5432 {
5433     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
5434                                           params.pipelineConstructionType);
5435 
5436     if (params.dynamicRendering)
5437     {
5438         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
5439     }
5440     else
5441     {
5442         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
5443         context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
5444     }
5445 
5446     const auto &dsResolveProperties = context.getDepthStencilResolveProperties();
5447 
5448     if ((dsResolveProperties.supportedDepthResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) == 0u)
5449         TCU_THROW(NotSupportedError, "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT not supported for depth");
5450 
5451     if ((dsResolveProperties.supportedStencilResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) == 0u)
5452         TCU_THROW(NotSupportedError, "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT not supported for stencil");
5453 
5454     if (params.testStencil())
5455         context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
5456 
5457     if (params.dynamicAlphaToCoverage)
5458     {
5459 #ifndef CTS_USES_VULKANSC
5460         const auto &eds3Features = context.getExtendedDynamicState3FeaturesEXT();
5461         if (!eds3Features.extendedDynamicState3AlphaToCoverageEnable)
5462             TCU_THROW(NotSupportedError, "extendedDynamicState3AlphaToCoverageEnable not supported");
5463 #else
5464         DE_ASSERT(false);
5465 #endif // CTS_USES_VULKANSC
5466     }
5467 }
5468 
ZExportInitPrograms(SourceCollections & programCollection,const ZExportParams params)5469 void ZExportInitPrograms(SourceCollections &programCollection, const ZExportParams params)
5470 {
5471     {
5472         const auto vertDepth = (params.testDepth() ? ZExportParams::kBadDepth : ZExportParams::kExpectedDepth);
5473 
5474         std::ostringstream vert;
5475         vert << "#version 460\n"
5476              << "vec2 positions[3] = vec2[](\n"
5477              << "    vec2(-1.0, -1.0),\n"
5478              << "    vec2(-1.0, 3.0),\n"
5479              << "    vec2(3.0, -1.0)\n"
5480              << ");\n"
5481              << "void main (void) {\n"
5482              << "    gl_Position = vec4(positions[gl_VertexIndex % 3], " << vertDepth << ", 1.0);\n"
5483              << "}\n";
5484         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
5485     }
5486 
5487     {
5488         std::ostringstream frag;
5489         frag << "#version 460\n"
5490              << "layout (location=0) out vec4 outColor;\n"
5491              << (params.testStencil() ? "#extension GL_ARB_shader_stencil_export: require\n" : "")
5492              << "void main (void) {\n"
5493              << "    const float alphaValue = ((int(gl_FragCoord.x) < " << (ZExportParams::kWidth / 2u)
5494              << ") ? 0.0 : 1.0);\n"
5495              << "    outColor = vec4(0.0, 0.0, 1.0, alphaValue);\n"
5496              << (params.testDepth() ? ("    gl_FragDepth = " + std::to_string(ZExportParams::kExpectedDepth) + ";\n") :
5497                                       "")
5498              << (params.testStencil() ?
5499                      ("    gl_FragStencilRefARB = " + std::to_string(ZExportParams::kExpectedStencil) + ";\n") :
5500                      "");
5501 
5502         if (params.testSampleMask())
5503             frag << "    gl_SampleMask[0] = ((int(gl_FragCoord.y) >= " << (ZExportParams::kHeight / 2u)
5504                  << ") ? 0 : 0xFF);\n";
5505 
5506         frag << "}\n";
5507         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
5508     }
5509 }
5510 
ZExportIterate(Context & context,const ZExportParams params)5511 tcu::TestStatus ZExportIterate(Context &context, const ZExportParams params)
5512 {
5513     const auto &ctx = context.getContextCommonData();
5514 
5515     // Choose depth/stencil format.
5516     const auto dsFormat = findSupportedDepthStencilFormat(context, true, true);
5517     if (dsFormat == VK_FORMAT_UNDEFINED)
5518         TCU_FAIL("Unable to find supported depth/stencil format");
5519 
5520     const auto fbExtent    = makeExtent3D(ZExportParams::kWidth, ZExportParams::kHeight, 1u);
5521     const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
5522     const auto colorUsage  = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
5523     const auto dsUsage     = (VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
5524     const auto colorAspect = VK_IMAGE_ASPECT_COLOR_BIT;
5525     const auto dsAspect    = (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
5526     const auto colorSRR    = makeImageSubresourceRange(colorAspect, 0u, 1u, 0u, 1u);
5527     const auto dsSRR       = makeImageSubresourceRange(dsAspect, 0u, 1u, 0u, 1u);
5528     const auto imageType   = VK_IMAGE_TYPE_2D;
5529     const auto viewType    = VK_IMAGE_VIEW_TYPE_2D;
5530     const auto sampleCount = VK_SAMPLE_COUNT_4_BIT;
5531     const auto bindPoint   = VK_PIPELINE_BIND_POINT_GRAPHICS;
5532 
5533     // Multisample color attachment.
5534     const VkImageCreateInfo colorAttachmentCreateInfo = {
5535         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
5536         nullptr,                             // const void* pNext;
5537         0u,                                  // VkImageCreateFlags flags;
5538         imageType,                           // VkImageType imageType;
5539         colorFormat,                         // VkFormat format;
5540         fbExtent,                            // VkExtent3D extent;
5541         1u,                                  // uint32_t mipLevels;
5542         1u,                                  // uint32_t arrayLayers;
5543         sampleCount,                         // VkSampleCountFlagBits samples;
5544         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
5545         colorUsage,                          // VkImageUsageFlags usage;
5546         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
5547         0u,                                  // uint32_t queueFamilyIndexCount;
5548         nullptr,                             // const uint32_t* pQueueFamilyIndices;
5549         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
5550     };
5551     ImageWithMemory colorAttachment(ctx.vkd, ctx.device, ctx.allocator, colorAttachmentCreateInfo,
5552                                     MemoryRequirement::Any);
5553     const auto colorAttachmentView =
5554         makeImageView(ctx.vkd, ctx.device, colorAttachment.get(), viewType, colorFormat, colorSRR);
5555 
5556     // Multisample depth/stencil attachment.
5557     const VkImageCreateInfo dsAttachmentCreateInfo = {
5558         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
5559         nullptr,                             // const void* pNext;
5560         0u,                                  // VkImageCreateFlags flags;
5561         imageType,                           // VkImageType imageType;
5562         dsFormat,                            // VkFormat format;
5563         fbExtent,                            // VkExtent3D extent;
5564         1u,                                  // uint32_t mipLevels;
5565         1u,                                  // uint32_t arrayLayers;
5566         sampleCount,                         // VkSampleCountFlagBits samples;
5567         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
5568         dsUsage,                             // VkImageUsageFlags usage;
5569         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
5570         0u,                                  // uint32_t queueFamilyIndexCount;
5571         nullptr,                             // const uint32_t* pQueueFamilyIndices;
5572         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
5573     };
5574     ImageWithMemory dsAttachment(ctx.vkd, ctx.device, ctx.allocator, dsAttachmentCreateInfo, MemoryRequirement::Any);
5575     const auto dsAttachmentView = makeImageView(ctx.vkd, ctx.device, dsAttachment.get(), viewType, dsFormat, dsSRR);
5576 
5577     // Resolve attachments.
5578     VkImageCreateInfo colorResolveAttachmentCreateInfo = colorAttachmentCreateInfo;
5579     colorResolveAttachmentCreateInfo.samples           = VK_SAMPLE_COUNT_1_BIT;
5580     VkImageCreateInfo dsResolveAttachmentCreateInfo    = dsAttachmentCreateInfo;
5581     dsResolveAttachmentCreateInfo.samples              = VK_SAMPLE_COUNT_1_BIT;
5582 
5583     ImageWithMemory colorResolveAttachment(ctx.vkd, ctx.device, ctx.allocator, colorResolveAttachmentCreateInfo,
5584                                            MemoryRequirement::Any);
5585     ImageWithMemory dsResolveAttachment(ctx.vkd, ctx.device, ctx.allocator, dsResolveAttachmentCreateInfo,
5586                                         MemoryRequirement::Any);
5587     const auto colorResolveAttachmentView =
5588         makeImageView(ctx.vkd, ctx.device, colorResolveAttachment.get(), viewType, colorFormat, colorSRR);
5589     const auto dsResolveAttachmentView =
5590         makeImageView(ctx.vkd, ctx.device, dsResolveAttachment.get(), viewType, dsFormat, dsSRR);
5591 
5592     // Render pass and framebuffer.
5593     const VkAttachmentDescription2 colorAttachmentDesc = {
5594         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5595         nullptr,
5596         0u,                                       // VkAttachmentDescriptionFlags flags;
5597         colorFormat,                              // VkFormat format;
5598         sampleCount,                              // VkSampleCountFlagBits samples;
5599         VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
5600         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp storeOp;
5601         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
5602         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
5603         VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
5604         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5605     };
5606     const VkAttachmentDescription2 dsAttachmentDesc = {
5607         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5608         nullptr,
5609         0u,                                               // VkAttachmentDescriptionFlags flags;
5610         dsFormat,                                         // VkFormat format;
5611         sampleCount,                                      // VkSampleCountFlagBits samples;
5612         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp loadOp;
5613         VK_ATTACHMENT_STORE_OP_DONT_CARE,                 // VkAttachmentStoreOp storeOp;
5614         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp stencilLoadOp;
5615         VK_ATTACHMENT_STORE_OP_DONT_CARE,                 // VkAttachmentStoreOp stencilStoreOp;
5616         VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout initialLayout;
5617         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5618     };
5619     const VkAttachmentDescription2 colorResolveAttachmentDesc = {
5620         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5621         nullptr,
5622         0u,                                       // VkAttachmentDescriptionFlags flags;
5623         colorFormat,                              // VkFormat format;
5624         VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
5625         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp loadOp;
5626         VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
5627         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
5628         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
5629         VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
5630         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5631     };
5632     const VkAttachmentDescription2 dsResolveAttachmentDesc = {
5633         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5634         nullptr,
5635         0u,                                               // VkAttachmentDescriptionFlags flags;
5636         dsFormat,                                         // VkFormat format;
5637         VK_SAMPLE_COUNT_1_BIT,                            // VkSampleCountFlagBits samples;
5638         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                  // VkAttachmentLoadOp loadOp;
5639         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp storeOp;
5640         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                  // VkAttachmentLoadOp stencilLoadOp;
5641         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp stencilStoreOp;
5642         VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout initialLayout;
5643         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5644     };
5645 
5646     std::vector<VkAttachmentDescription2> attachmentDescriptions;
5647     attachmentDescriptions.reserve(4u);
5648     attachmentDescriptions.push_back(colorAttachmentDesc);
5649     attachmentDescriptions.push_back(dsAttachmentDesc);
5650     attachmentDescriptions.push_back(colorResolveAttachmentDesc);
5651     attachmentDescriptions.push_back(dsResolveAttachmentDesc);
5652 
5653     const VkAttachmentReference2 colorAttachmentReference = {
5654         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorAspect,
5655     };
5656     const VkAttachmentReference2 dsAttachmentReference = {
5657         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,         nullptr,  1u,
5658         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, dsAspect,
5659     };
5660     const VkAttachmentReference2 colorResolveAttachmentReference = {
5661         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, 2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorAspect,
5662     };
5663     const VkAttachmentReference2 dsResolveAttachmentReference = {
5664         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,         nullptr,  3u,
5665         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, dsAspect,
5666     };
5667 
5668     const VkSubpassDescriptionDepthStencilResolve dsResolveDescription = {
5669         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, // VkStructureType sType;
5670         nullptr,                                                     // const void* pNext;
5671         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,                             // VkResolveModeFlagBits depthResolveMode;
5672         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,                             // VkResolveModeFlagBits stencilResolveMode;
5673         &dsResolveAttachmentReference, // const VkAttachmentReference2* pDepthStencilResolveAttachment;
5674     };
5675 
5676     const VkSubpassDescription2 subpassDescription = {
5677         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
5678         &dsResolveDescription,
5679         0u,                               // VkSubpassDescriptionFlags flags;
5680         bindPoint,                        // VkPipelineBindPoint pipelineBindPoint;
5681         0u,                               // uint32_t viewMask;
5682         0u,                               // uint32_t inputAttachmentCount;
5683         nullptr,                          // const VkAttachmentReference* pInputAttachments;
5684         1u,                               // uint32_t colorAttachmentCount;
5685         &colorAttachmentReference,        // const VkAttachmentReference* pColorAttachments;
5686         &colorResolveAttachmentReference, // const VkAttachmentReference* pResolveAttachments;
5687         &dsAttachmentReference,           // const VkAttachmentReference* pDepthStencilAttachment;
5688         0u,                               // uint32_t preserveAttachmentCount;
5689         nullptr,                          // const uint32_t* pPreserveAttachments;
5690     };
5691 
5692     const VkRenderPassCreateInfo2 renderPassCreateInfo = {
5693         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType sType;
5694         nullptr,                                     // const void* pNext;
5695         0u,                                          // VkRenderPassCreateFlags flags;
5696         de::sizeU32(attachmentDescriptions),         // uint32_t attachmentCount;
5697         de::dataOrNull(attachmentDescriptions),      // const VkAttachmentDescription* pAttachments;
5698         1u,                                          // uint32_t subpassCount;
5699         &subpassDescription,                         // const VkSubpassDescription* pSubpasses;
5700         0u,                                          // uint32_t dependencyCount;
5701         nullptr,                                     // const VkSubpassDependency* pDependencies;
5702         0u,                                          // uint32_t correlatedViewMaskCount;
5703         nullptr,                                     // const uint32_t* pCorrelatedViewMasks;
5704     };
5705 
5706     const std::vector<VkImage> images{
5707         *colorAttachment,
5708         *dsAttachment,
5709         *colorResolveAttachment,
5710         *dsResolveAttachment,
5711     };
5712 
5713     const std::vector<VkImageView> attachmentViews{
5714         colorAttachmentView.get(),
5715         dsAttachmentView.get(),
5716         colorResolveAttachmentView.get(),
5717         dsResolveAttachmentView.get(),
5718     };
5719 
5720     RenderPassWrapper renderPass(
5721         ctx.vkd, ctx.device, &renderPassCreateInfo,
5722         (params.dynamicRendering || isConstructionTypeShaderObject(params.pipelineConstructionType)));
5723     renderPass.createFramebuffer(ctx.vkd, ctx.device, de::sizeU32(attachmentViews), de::dataOrNull(images),
5724                                  de::dataOrNull(attachmentViews), fbExtent.width, fbExtent.height);
5725 
5726     // Pipeline layout.
5727     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, ctx.vkd, ctx.device);
5728 
5729     // Shaders.
5730     const auto &binaries  = context.getBinaryCollection();
5731     const auto vertShader = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("vert"));
5732     const auto fragShader = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("frag"));
5733     const auto nullShader = ShaderWrapper();
5734 
5735     // Viewports and scissors.
5736     const std::vector<VkViewport> viewports(1u, makeViewport(fbExtent));
5737     const std::vector<VkRect2D> scissors(1u, makeRect2D(fbExtent));
5738 
5739     const auto frontStencilRef = (params.testStencil() ? ZExportParams::kBadStencil : ZExportParams::kExpectedStencil);
5740     const VkStencilOpState frontStencilOpState{
5741         VK_STENCIL_OP_KEEP,    // VkStencilOp                                    failOp
5742         VK_STENCIL_OP_REPLACE, // VkStencilOp                                    passOp
5743         VK_STENCIL_OP_KEEP,    // VkStencilOp                                    depthFailOp
5744         VK_COMPARE_OP_ALWAYS,  // VkCompareOp                                    compareOp
5745         0xFFu,                 // uint32_t                                        compareMask
5746         0xFFu,                 // uint32_t                                        writeMask
5747         frontStencilRef,       // uint32_t                                        reference
5748     };
5749     const auto backStencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP,
5750                                                        VK_COMPARE_OP_NEVER, 0xFFu, 0xFFu, 0u);
5751 
5752     const VkPipelineDepthStencilStateCreateInfo dsStateInfo{
5753         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                                sType
5754         DE_NULL,             // const void*                                    pNext
5755         0u,                  // VkPipelineDepthStencilStateCreateFlags        flags
5756         VK_TRUE,             // VkBool32                                        depthTestEnable
5757         VK_TRUE,             // VkBool32                                        depthWriteEnable
5758         VK_COMPARE_OP_LESS,  // VkCompareOp                                    depthCompareOp
5759         VK_FALSE,            // VkBool32                                        depthBoundsTestEnable
5760         VK_TRUE,             // VkBool32                                        stencilTestEnable
5761         frontStencilOpState, // VkStencilOpState                                front
5762         backStencilOpState,  // VkStencilOpState                                back
5763         0.0f,                // float                                        minDepthBounds
5764         1.0f,                // float                                        maxDepthBounds
5765     };
5766 
5767     // Multisample state, including alpha to coverage, which is key for these tests.
5768     const auto staticAlphaToCoverage = (params.dynamicAlphaToCoverage ? VK_FALSE : VK_TRUE);
5769     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo{
5770         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                                sType
5771         nullptr,               // const void*                                    pNext
5772         0u,                    // VkPipelineMultisampleStateCreateFlags        flags
5773         sampleCount,           // VkSampleCountFlagBits                        rasterizationSamples
5774         VK_FALSE,              // VkBool32                                        sampleShadingEnable
5775         1.0f,                  // float                                        minSampleShading
5776         nullptr,               // const VkSampleMask*                            pSampleMask
5777         staticAlphaToCoverage, // VkBool32                                        alphaToCoverageEnable
5778         VK_FALSE,              // VkBool32                                        alphaToOneEnable
5779     };
5780 
5781     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
5782 
5783     std::vector<VkDynamicState> dynamicStates;
5784 #ifndef CTS_USES_VULKANSC
5785     if (params.dynamicAlphaToCoverage)
5786         dynamicStates.push_back(VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
5787 #else
5788     DE_ASSERT(false);
5789 #endif // CTS_USES_VULKANSC
5790 
5791     const VkPipelineDynamicStateCreateInfo dynamicStateInfo = {
5792         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
5793         nullptr,                                              // const void* pNext;
5794         0u,                                                   // VkPipelineDynamicStateCreateFlags flags;
5795         de::sizeU32(dynamicStates),                           // uint32_t dynamicStateCount;
5796         de::dataOrNull(dynamicStates),                        // const VkDynamicState* pDynamicStates;
5797     };
5798 
5799 #ifndef CTS_USES_VULKANSC
5800     VkPipelineRenderingCreateInfo renderingCreateInfo = {
5801         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType sType;
5802         nullptr,                                          // const void* pNext;
5803         0u,                                               // uint32_t viewMask;
5804         1u,                                               // uint32_t colorAttachmentCount;
5805         &colorFormat,                                     // const VkFormat* pColorAttachmentFormats;
5806         dsFormat,                                         // VkFormat depthAttachmentFormat;
5807         dsFormat,                                         // VkFormat stencilAttachmentFormat;
5808     };
5809 
5810     PipelineRenderingCreateInfoWrapper renderingCreateInfoPtr(params.dynamicRendering ? &renderingCreateInfo : nullptr);
5811 #else
5812     PipelineRenderingCreateInfoWrapper renderingCreateInfoPtr(nullptr);
5813 #endif // CTS_USES_VULKANSC
5814 
5815     const auto fragShaderStateMSPtr = (params.dynamicRendering ? nullptr : &multisampleStateCreateInfo);
5816 
5817     GraphicsPipelineWrapper pipelineWrapper(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device,
5818                                             context.getDeviceExtensions(), params.pipelineConstructionType);
5819     pipelineWrapper.setDefaultRasterizationState()
5820         .setDefaultColorBlendState()
5821         .setDynamicState(&dynamicStateInfo)
5822         .setupVertexInputState(&vertexInputStateCreateInfo)
5823         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertShader, nullptr,
5824                                           nullShader, nullShader, nullShader, nullptr, nullptr, renderingCreateInfoPtr)
5825         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragShader, &dsStateInfo, fragShaderStateMSPtr,
5826                                   nullptr, VK_NULL_HANDLE)
5827         .setupFragmentOutputState(*renderPass, 0u, nullptr, &multisampleStateCreateInfo)
5828         .setMonolithicPipelineLayout(pipelineLayout)
5829         .buildPipeline();
5830 
5831     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
5832     const auto cmdBuffer = *cmd.cmdBuffer;
5833 
5834     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 0.0f);
5835     const tcu::Vec4 geometryColor(0.0f, 0.0f, 1.0f, 1.0f); // For pixels with coverage. Must match frag shader.
5836 
5837     const std::vector<VkClearValue> clearValues{
5838         makeClearValueColor(clearColor),
5839         makeClearValueDepthStencil(ZExportParams::kClearDepth, ZExportParams::kClearStencil),
5840     };
5841 
5842     beginCommandBuffer(ctx.vkd, cmdBuffer);
5843     renderPass.begin(ctx.vkd, cmdBuffer, scissors.at(0u), de::sizeU32(clearValues), de::dataOrNull(clearValues));
5844     pipelineWrapper.bind(cmdBuffer);
5845 #ifndef CTS_USES_VULKANSC
5846     if (params.dynamicAlphaToCoverage)
5847         ctx.vkd.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, VK_TRUE);
5848 #else
5849     DE_ASSERT(false);
5850 #endif // CTS_USES_VULKANSC
5851     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
5852     renderPass.end(ctx.vkd, cmdBuffer);
5853     endCommandBuffer(ctx.vkd, cmdBuffer);
5854     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
5855 
5856     const tcu::UVec2 renderSize(fbExtent.width, fbExtent.height);
5857     const auto colorLevel = readColorAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator,
5858                                                 colorResolveAttachment.get(), colorFormat, renderSize);
5859     const auto depthLevel = readDepthAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator,
5860                                                 dsResolveAttachment.get(), dsFormat, renderSize);
5861     const auto stencilLevel =
5862         readStencilAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator, dsResolveAttachment.get(),
5863                               dsFormat, renderSize, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
5864 
5865     const auto colorAccess   = colorLevel->getAccess();
5866     const auto depthAccess   = depthLevel->getAccess();
5867     const auto stencilAccess = stencilLevel->getAccess();
5868 
5869     const tcu::IVec3 iExtent(static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height),
5870                              static_cast<int>(fbExtent.depth));
5871     tcu::TextureLevel refColor(mapVkFormat(colorFormat), iExtent.x(), iExtent.y());
5872     tcu::TextureLevel refDepth(getDepthCopyFormat(dsFormat), iExtent.x(), iExtent.y());
5873     tcu::TextureLevel refStencil(getStencilCopyFormat(dsFormat), iExtent.x(), iExtent.y());
5874 
5875     auto refColorAccess   = refColor.getAccess();
5876     auto refDepthAccess   = refDepth.getAccess();
5877     auto refStencilAccess = refStencil.getAccess();
5878 
5879     const auto halfWidth  = iExtent.x() / 2;
5880     const auto halfHeight = iExtent.y() / 2;
5881 
5882     const tcu::Vec4 geometryColorNoAlpha(geometryColor.x(), geometryColor.y(), geometryColor.z(),
5883                                          0.0f); // For pixels with coverage but alpha set to 0
5884 
5885     // allow skipping alpha to coverage if sample mask output is used
5886     std::vector<bool> skipAlphaToCoverageBehaviors =
5887         (params.testSampleMask() ? std::vector<bool>({false, true}) : std::vector<bool>({false}));
5888 
5889     for (bool skipAlphaToCoverage : skipAlphaToCoverageBehaviors)
5890     {
5891 
5892         // Prepare color reference.
5893         {
5894             auto topLeft     = tcu::getSubregion(refColorAccess, 0, 0, halfWidth, halfHeight);
5895             auto bottomLeft  = tcu::getSubregion(refColorAccess, 0, halfHeight, halfWidth, halfHeight);
5896             auto topRight    = tcu::getSubregion(refColorAccess, halfWidth, 0, halfWidth, halfHeight);
5897             auto bottomRight = tcu::getSubregion(refColorAccess, halfWidth, halfHeight, halfWidth, halfHeight);
5898 
5899             tcu::clear(topLeft, (skipAlphaToCoverage ? geometryColorNoAlpha : clearColor));
5900             tcu::clear(
5901                 bottomLeft,
5902                 (skipAlphaToCoverage ? (params.testSampleMask() ? clearColor : geometryColorNoAlpha) : clearColor));
5903             tcu::clear(topRight, geometryColor);
5904             tcu::clear(bottomRight, (params.testSampleMask() ? clearColor : geometryColor));
5905         }
5906         // Prepare depth reference.
5907         {
5908             auto topLeft     = tcu::getSubregion(refDepthAccess, 0, 0, halfWidth, halfHeight);
5909             auto bottomLeft  = tcu::getSubregion(refDepthAccess, 0, halfHeight, halfWidth, halfHeight);
5910             auto topRight    = tcu::getSubregion(refDepthAccess, halfWidth, 0, halfWidth, halfHeight);
5911             auto bottomRight = tcu::getSubregion(refDepthAccess, halfWidth, halfHeight, halfWidth, halfHeight);
5912 
5913             tcu::clearDepth(topLeft,
5914                             (skipAlphaToCoverage ? ZExportParams::kExpectedDepth : ZExportParams::kClearDepth));
5915             tcu::clearDepth(bottomLeft,
5916                             (skipAlphaToCoverage ? (params.testSampleMask() ? ZExportParams::kClearDepth :
5917                                                                               ZExportParams::kExpectedDepth) :
5918                                                    ZExportParams::kClearDepth));
5919             tcu::clearDepth(topRight, ZExportParams::kExpectedDepth);
5920             tcu::clearDepth(bottomRight,
5921                             (params.testSampleMask() ? ZExportParams::kClearDepth : ZExportParams::kExpectedDepth));
5922         }
5923         // Prepare stencil reference.
5924         {
5925             const auto clearStencil    = static_cast<int>(ZExportParams::kClearStencil);
5926             const auto expectedStencil = static_cast<int>(ZExportParams::kExpectedStencil);
5927 
5928             auto topLeft     = tcu::getSubregion(refStencilAccess, 0, 0, halfWidth, halfHeight);
5929             auto bottomLeft  = tcu::getSubregion(refStencilAccess, 0, halfHeight, halfWidth, halfHeight);
5930             auto topRight    = tcu::getSubregion(refStencilAccess, halfWidth, 0, halfWidth, halfHeight);
5931             auto bottomRight = tcu::getSubregion(refStencilAccess, halfWidth, halfHeight, halfWidth, halfHeight);
5932 
5933             tcu::clearStencil(topLeft, (skipAlphaToCoverage ? expectedStencil : clearStencil));
5934             tcu::clearStencil(
5935                 bottomLeft,
5936                 (skipAlphaToCoverage ? (params.testSampleMask() ? clearStencil : expectedStencil) : clearStencil));
5937             tcu::clearStencil(topRight, expectedStencil);
5938             tcu::clearStencil(bottomRight, (params.testSampleMask() ? clearStencil : expectedStencil));
5939         }
5940 
5941         // Compare results and references.
5942         auto &log            = context.getTestContext().getLog();
5943         const auto colorOK   = tcu::floatThresholdCompare(log, "Color", "Color Result", refColorAccess, colorAccess,
5944                                                           tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_ON_ERROR);
5945         const auto depthOK   = tcu::dsThresholdCompare(log, "Depth", "Depth Result", refDepthAccess, depthAccess, 0.0f,
5946                                                        tcu::COMPARE_LOG_ON_ERROR);
5947         const auto stencilOK = tcu::dsThresholdCompare(log, "Stencil", "Stencil Result", refStencilAccess,
5948                                                        stencilAccess, 0.0f, tcu::COMPARE_LOG_ON_ERROR);
5949 
5950         if (colorOK && depthOK && stencilOK)
5951             return tcu::TestStatus::pass("Pass");
5952     }
5953 
5954     return tcu::TestStatus::fail("Unexpected color, depth or stencil result; check log for details");
5955 }
5956 
5957 } // namespace
5958 
createMultisampleTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)5959 tcu::TestCaseGroup *createMultisampleTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType,
5960                                            bool useFragmentShadingRate)
5961 {
5962     using TestCaseGroupPtr = de::MovePtr<tcu::TestCaseGroup>;
5963 
5964     const VkSampleCountFlagBits samples[] = {VK_SAMPLE_COUNT_2_BIT,  VK_SAMPLE_COUNT_4_BIT,  VK_SAMPLE_COUNT_8_BIT,
5965                                              VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_64_BIT};
5966 
5967     const char *groupName[]{"multisample", "multisample_with_fragment_shading_rate"};
5968     TestCaseGroupPtr multisampleTests(new tcu::TestCaseGroup(testCtx, groupName[useFragmentShadingRate]));
5969 
5970     // Rasterization samples tests
5971     {
5972         TestCaseGroupPtr rasterizationSamplesTests(new tcu::TestCaseGroup(testCtx, "raster_samples"));
5973 
5974         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
5975         {
5976             std::ostringstream caseName;
5977             caseName << "samples_" << samples[samplesNdx];
5978 
5979             TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
5980 
5981             samplesTests->addChild(new RasterizationSamplesTest(
5982                 testCtx, "primitive_triangle", pipelineConstructionType, samples[samplesNdx],
5983                 GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
5984             samplesTests->addChild(new RasterizationSamplesTest(
5985                 testCtx, "primitive_line", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE,
5986                 1.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
5987             samplesTests->addChild(new RasterizationSamplesTest(
5988                 testCtx, "primitive_point_1px", pipelineConstructionType, samples[samplesNdx],
5989                 GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
5990             samplesTests->addChild(new RasterizationSamplesTest(
5991                 testCtx, "primitive_point", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT,
5992                 3.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
5993 
5994             samplesTests->addChild(new RasterizationSamplesTest(
5995                 testCtx, "depth", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f,
5996                 IMAGE_BACKING_MODE_REGULAR, TEST_MODE_DEPTH_BIT, useFragmentShadingRate));
5997             samplesTests->addChild(new RasterizationSamplesTest(
5998                 testCtx, "stencil", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE,
5999                 1.0f, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6000             samplesTests->addChild(
6001                 new RasterizationSamplesTest(testCtx, "depth_stencil", pipelineConstructionType, samples[samplesNdx],
6002                                              GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR,
6003                                              TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6004 
6005 #ifndef CTS_USES_VULKANSC
6006             samplesTests->addChild(new RasterizationSamplesTest(
6007                 testCtx, "primitive_triangle_sparse", pipelineConstructionType, samples[samplesNdx],
6008                 GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6009             samplesTests->addChild(new RasterizationSamplesTest(
6010                 testCtx, "primitive_line_sparse", pipelineConstructionType, samples[samplesNdx],
6011                 GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6012             samplesTests->addChild(new RasterizationSamplesTest(
6013                 testCtx, "primitive_point_1px_sparse", pipelineConstructionType, samples[samplesNdx],
6014                 GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6015             samplesTests->addChild(new RasterizationSamplesTest(
6016                 testCtx, "primitive_point_sparse", pipelineConstructionType, samples[samplesNdx],
6017                 GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6018 
6019             samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_sparse", pipelineConstructionType,
6020                                                                 samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE,
6021                                                                 1.0f, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_DEPTH_BIT,
6022                                                                 useFragmentShadingRate));
6023             samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil_sparse", pipelineConstructionType,
6024                                                                 samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE,
6025                                                                 1.0f, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_STENCIL_BIT,
6026                                                                 useFragmentShadingRate));
6027             samplesTests->addChild(new RasterizationSamplesTest(
6028                 testCtx, "depth_stencil_sparse", pipelineConstructionType, samples[samplesNdx],
6029                 GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE,
6030                 TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6031 #endif // CTS_USES_VULKANSC
6032             rasterizationSamplesTests->addChild(samplesTests.release());
6033         }
6034 
6035         multisampleTests->addChild(rasterizationSamplesTests.release());
6036     }
6037 
6038     // Raster samples consistency check
6039 #ifndef CTS_USES_VULKANSC
6040     {
6041         TestCaseGroupPtr rasterSamplesConsistencyTests(new tcu::TestCaseGroup(testCtx, "raster_samples_consistency"));
6042         MultisampleTestParams paramsRegular = {pipelineConstructionType, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f,
6043                                                IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate};
6044         MultisampleTestParams paramsSparse  = {pipelineConstructionType, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f,
6045                                                IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate};
6046 
6047         addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(), "unique_colors_check", checkSupport,
6048                                     initMultisamplePrograms, testRasterSamplesConsistency, paramsRegular);
6049         addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(), "unique_colors_check_sparse", checkSupport,
6050                                     initMultisamplePrograms, testRasterSamplesConsistency, paramsSparse);
6051         multisampleTests->addChild(rasterSamplesConsistencyTests.release());
6052     }
6053 #endif // CTS_USES_VULKANSC
6054 
6055     // minSampleShading tests
6056     {
6057         struct TestConfig
6058         {
6059             const char *name;
6060             float minSampleShading;
6061         };
6062 
6063         const TestConfig testConfigs[] = {
6064             {"min_0_0", 0.0f}, {"min_0_25", 0.25f}, {"min_0_5", 0.5f}, {"min_0_75", 0.75f}, {"min_1_0", 1.0f}};
6065 
6066         // Input attachments are not supported with dynamic rendering and shader objects
6067         if (!isConstructionTypeShaderObject(pipelineConstructionType))
6068         {
6069             TestCaseGroupPtr minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading"));
6070             {
6071                 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6072                 {
6073                     const TestConfig &testConfig = testConfigs[configNdx];
6074 
6075                     // minSampleShading is not supported by shader objects
6076                     if (testConfig.minSampleShading != 1.0f && isConstructionTypeShaderObject(pipelineConstructionType))
6077                         continue;
6078 
6079                     TestCaseGroupPtr minShadingValueTests(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name));
6080 
6081                     for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6082                     {
6083                         std::ostringstream caseName;
6084                         caseName << "samples_" << samples[samplesNdx];
6085 
6086                         TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6087 
6088                         samplesTests->addChild(new MinSampleShadingTest(
6089                             testCtx, "primitive_triangle", pipelineConstructionType, samples[samplesNdx],
6090                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f,
6091                             IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6092                         samplesTests->addChild(new MinSampleShadingTest(
6093                             testCtx, "primitive_line", pipelineConstructionType, samples[samplesNdx],
6094                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_REGULAR,
6095                             true, useFragmentShadingRate));
6096                         samplesTests->addChild(new MinSampleShadingTest(
6097                             testCtx, "primitive_point_1px", pipelineConstructionType, samples[samplesNdx],
6098                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_REGULAR,
6099                             true, useFragmentShadingRate));
6100                         samplesTests->addChild(new MinSampleShadingTest(
6101                             testCtx, "primitive_point", pipelineConstructionType, samples[samplesNdx],
6102                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_REGULAR,
6103                             true, useFragmentShadingRate));
6104 #ifndef CTS_USES_VULKANSC
6105                         samplesTests->addChild(new MinSampleShadingTest(
6106                             testCtx, "primitive_triangle_sparse", pipelineConstructionType, samples[samplesNdx],
6107                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE,
6108                             true, useFragmentShadingRate));
6109                         samplesTests->addChild(new MinSampleShadingTest(
6110                             testCtx, "primitive_line_sparse", pipelineConstructionType, samples[samplesNdx],
6111                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_SPARSE,
6112                             true, useFragmentShadingRate));
6113                         samplesTests->addChild(new MinSampleShadingTest(
6114                             testCtx, "primitive_point_1px_sparse", pipelineConstructionType, samples[samplesNdx],
6115                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_SPARSE,
6116                             true, useFragmentShadingRate));
6117                         samplesTests->addChild(new MinSampleShadingTest(
6118                             testCtx, "primitive_point_sparse", pipelineConstructionType, samples[samplesNdx],
6119                             testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_SPARSE,
6120                             true, useFragmentShadingRate));
6121 #endif // CTS_USES_VULKANSC
6122 
6123                         minShadingValueTests->addChild(samplesTests.release());
6124                     }
6125 
6126                     minSampleShadingTests->addChild(minShadingValueTests.release());
6127                 }
6128 
6129                 multisampleTests->addChild(minSampleShadingTests.release());
6130             }
6131         }
6132 
6133         // Input attachments are not supported with dynamic rendering and shader objects
6134         if (!isConstructionTypeShaderObject(pipelineConstructionType))
6135         {
6136             TestCaseGroupPtr minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading_enabled"));
6137 
6138             for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6139             {
6140                 const TestConfig &testConfig = testConfigs[configNdx];
6141                 TestCaseGroupPtr minShadingValueTests(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name));
6142 
6143                 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6144                 {
6145                     std::ostringstream caseName;
6146                     caseName << "samples_" << samples[samplesNdx];
6147 
6148                     TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6149 
6150                     samplesTests->addChild(new MinSampleShadingTest(
6151                         testCtx, "quad", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading,
6152                         GEOMETRY_TYPE_OPAQUE_QUAD, 1.0f, IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6153 
6154                     minShadingValueTests->addChild(samplesTests.release());
6155                 }
6156 
6157                 minSampleShadingTests->addChild(minShadingValueTests.release());
6158             }
6159 
6160             multisampleTests->addChild(minSampleShadingTests.release());
6161         }
6162 
6163         // Input attachments are not supported with dynamic rendering and shader objects
6164         if (!isConstructionTypeShaderObject(pipelineConstructionType))
6165         {
6166             TestCaseGroupPtr minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading_disabled"));
6167 
6168             for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6169             {
6170                 const TestConfig &testConfig = testConfigs[configNdx];
6171                 TestCaseGroupPtr minShadingValueTests(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name));
6172 
6173                 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6174                 {
6175                     std::ostringstream caseName;
6176                     caseName << "samples_" << samples[samplesNdx];
6177 
6178                     TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6179 
6180                     samplesTests->addChild(new MinSampleShadingTest(
6181                         testCtx, "quad", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading,
6182                         GEOMETRY_TYPE_OPAQUE_QUAD, 1.0f, IMAGE_BACKING_MODE_REGULAR, false, useFragmentShadingRate));
6183 
6184                     minShadingValueTests->addChild(samplesTests.release());
6185                 }
6186 
6187                 minSampleShadingTests->addChild(minShadingValueTests.release());
6188             }
6189 
6190             multisampleTests->addChild(minSampleShadingTests.release());
6191         }
6192     }
6193 
6194     // SampleMask tests
6195     {
6196         struct TestConfig
6197         {
6198             const char *name;
6199             VkSampleMask sampleMask;
6200         };
6201 
6202         const TestConfig testConfigs[] = {
6203             // All mask bits are off
6204             {"mask_all_on", 0x0},
6205             // All mask bits are on
6206             {"mask_all_off", 0xFFFFFFFF},
6207             // All mask elements are 0x1
6208             {"mask_one", 0x1},
6209             // All mask elements are 0xAAAAAAAA
6210             {"mask_random", 0xAAAAAAAA},
6211         };
6212 
6213         TestCaseGroupPtr sampleMaskTests(new tcu::TestCaseGroup(testCtx, "sample_mask"));
6214 
6215         for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6216         {
6217             const TestConfig &testConfig = testConfigs[configNdx];
6218             TestCaseGroupPtr sampleMaskValueTests(new tcu::TestCaseGroup(testCtx, testConfig.name));
6219 
6220             for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6221             {
6222                 std::ostringstream caseName;
6223                 caseName << "samples_" << samples[samplesNdx];
6224 
6225                 const uint32_t sampleMaskCount = samples[samplesNdx] / 32;
6226                 TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6227 
6228                 std::vector<VkSampleMask> mask;
6229                 for (uint32_t maskNdx = 0; maskNdx < sampleMaskCount; maskNdx++)
6230                     mask.push_back(testConfig.sampleMask);
6231 
6232                 samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle", pipelineConstructionType,
6233                                                           samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE,
6234                                                           1.0f, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6235                 samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line", pipelineConstructionType,
6236                                                           samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f,
6237                                                           IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6238                 samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point_1px", pipelineConstructionType,
6239                                                           samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f,
6240                                                           IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6241                 samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point", pipelineConstructionType,
6242                                                           samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f,
6243                                                           IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6244 #ifndef CTS_USES_VULKANSC
6245                 samplesTests->addChild(new SampleMaskTest(
6246                     testCtx, "primitive_triangle_sparse", pipelineConstructionType, samples[samplesNdx], mask,
6247                     GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6248                 samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line_sparse", pipelineConstructionType,
6249                                                           samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f,
6250                                                           IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6251                 samplesTests->addChild(new SampleMaskTest(
6252                     testCtx, "primitive_point_1px_sparse", pipelineConstructionType, samples[samplesNdx], mask,
6253                     GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6254                 samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point_sparse", pipelineConstructionType,
6255                                                           samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f,
6256                                                           IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6257 #endif // CTS_USES_VULKANSC
6258 
6259                 sampleMaskValueTests->addChild(samplesTests.release());
6260             }
6261 
6262             sampleMaskTests->addChild(sampleMaskValueTests.release());
6263         }
6264 
6265         multisampleTests->addChild(sampleMaskTests.release());
6266     }
6267 
6268     // AlphaToOne tests
6269     {
6270         const VkSampleCountFlagBits samplesForAlphaToOne[] = {
6271             VK_SAMPLE_COUNT_1_BIT,  VK_SAMPLE_COUNT_2_BIT,  VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
6272             VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_64_BIT};
6273         TestCaseGroupPtr alphaToOneTests(new tcu::TestCaseGroup(testCtx, "alpha_to_one"));
6274 
6275         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samplesForAlphaToOne); samplesNdx++)
6276         {
6277             std::ostringstream caseName;
6278             caseName << "samples_" << samplesForAlphaToOne[samplesNdx];
6279 
6280             alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), pipelineConstructionType,
6281                                                          samplesForAlphaToOne[samplesNdx], IMAGE_BACKING_MODE_REGULAR,
6282                                                          useFragmentShadingRate));
6283 #ifndef CTS_USES_VULKANSC
6284             caseName << "_sparse";
6285             alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), pipelineConstructionType,
6286                                                          samplesForAlphaToOne[samplesNdx], IMAGE_BACKING_MODE_SPARSE,
6287                                                          useFragmentShadingRate));
6288 #endif // CTS_USES_VULKANSC
6289         }
6290 
6291         multisampleTests->addChild(alphaToOneTests.release());
6292     }
6293 
6294     // AlphaToCoverageEnable tests
6295     {
6296         TestCaseGroupPtr alphaToCoverageTests(new tcu::TestCaseGroup(testCtx, "alpha_to_coverage"));
6297 
6298         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6299         {
6300             std::ostringstream caseName;
6301             caseName << "samples_" << samples[samplesNdx];
6302 
6303             TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6304 
6305             samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque", pipelineConstructionType,
6306                                                            samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD,
6307                                                            IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, false));
6308             samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent", pipelineConstructionType,
6309                                                            samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD,
6310                                                            IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, false));
6311             samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible", pipelineConstructionType,
6312                                                            samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD,
6313                                                            IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, false));
6314             samplesTests->addChild(new AlphaToCoverageTest(
6315                 testCtx, "alpha_invisible_check_depth", pipelineConstructionType, samples[samplesNdx],
6316                 GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, true));
6317 #ifndef CTS_USES_VULKANSC
6318             samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque_sparse", pipelineConstructionType,
6319                                                            samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD,
6320                                                            IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, false));
6321             samplesTests->addChild(new AlphaToCoverageTest(
6322                 testCtx, "alpha_translucent_sparse", pipelineConstructionType, samples[samplesNdx],
6323                 GEOMETRY_TYPE_TRANSLUCENT_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, false));
6324             samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible_sparse", pipelineConstructionType,
6325                                                            samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD,
6326                                                            IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, false));
6327             samplesTests->addChild(new AlphaToCoverageTest(
6328                 testCtx, "alpha_invisible_sparse_check_depth", pipelineConstructionType, samples[samplesNdx],
6329                 GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, true));
6330 #endif // CTS_USES_VULKANSC
6331 
6332             alphaToCoverageTests->addChild(samplesTests.release());
6333         }
6334         multisampleTests->addChild(alphaToCoverageTests.release());
6335     }
6336 
6337     // AlphaToCoverageEnable without color buffer tests
6338     {
6339         TestCaseGroupPtr alphaToCoverageNoColorAttachmentTests(
6340             new tcu::TestCaseGroup(testCtx, "alpha_to_coverage_no_color_attachment"));
6341 
6342         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6343         {
6344             std::ostringstream caseName;
6345             caseName << "samples_" << samples[samplesNdx];
6346 
6347             TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6348 
6349             samplesTests->addChild(new AlphaToCoverageNoColorAttachmentTest(
6350                 testCtx, "alpha_opaque", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD,
6351                 IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6352 #ifndef CTS_USES_VULKANSC
6353             samplesTests->addChild(new AlphaToCoverageNoColorAttachmentTest(
6354                 testCtx, "alpha_opaque_sparse", pipelineConstructionType, samples[samplesNdx],
6355                 GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6356 #endif // CTS_USES_VULKANSC
6357 
6358             alphaToCoverageNoColorAttachmentTests->addChild(samplesTests.release());
6359         }
6360         multisampleTests->addChild(alphaToCoverageNoColorAttachmentTests.release());
6361     }
6362 
6363     // AlphaToCoverageEnable with unused color attachment:
6364     // Set color output at location 0 as unused, but use the alpha write to control coverage for rendering to color buffer at location 1.
6365     {
6366         TestCaseGroupPtr alphaToCoverageColorUnusedAttachmentTests(
6367             new tcu::TestCaseGroup(testCtx, "alpha_to_coverage_unused_attachment"));
6368 
6369         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6370         {
6371             std::ostringstream caseName;
6372             caseName << "samples_" << samples[samplesNdx];
6373 
6374             TestCaseGroupPtr samplesTests(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6375 
6376             samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(
6377                 testCtx, "alpha_opaque", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD,
6378                 IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6379 #ifndef CTS_USES_VULKANSC
6380             samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(
6381                 testCtx, "alpha_opaque_sparse", pipelineConstructionType, samples[samplesNdx],
6382                 GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6383 #endif // CTS_USES_VULKANSC
6384             samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(
6385                 testCtx, "alpha_invisible", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD,
6386                 IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6387 #ifndef CTS_USES_VULKANSC
6388             samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(
6389                 testCtx, "alpha_invisible_sparse", pipelineConstructionType, samples[samplesNdx],
6390                 GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6391 #endif // CTS_USES_VULKANSC
6392 
6393             alphaToCoverageColorUnusedAttachmentTests->addChild(samplesTests.release());
6394         }
6395         multisampleTests->addChild(alphaToCoverageColorUnusedAttachmentTests.release());
6396     }
6397 
6398 #ifndef CTS_USES_VULKANSC
6399     // not all tests need to be repeated for FSR
6400     if (useFragmentShadingRate == false)
6401     {
6402         // Sampling from a multisampled image texture (texelFetch)
6403         multisampleTests->addChild(createMultisampleSampledImageTests(testCtx, pipelineConstructionType));
6404 
6405         // Load/store on a multisampled rendered image (different kinds of access: color attachment write, storage image, etc.)
6406         multisampleTests->addChild(createMultisampleStorageImageTests(testCtx, pipelineConstructionType));
6407 
6408         // Sampling from a multisampled image texture (texelFetch), checking supersample positions
6409         multisampleTests->addChild(createMultisampleStandardSamplePositionTests(testCtx, pipelineConstructionType));
6410 
6411         // VK_AMD_shader_fragment_mask
6412         multisampleTests->addChild(createMultisampleShaderFragmentMaskTests(testCtx, pipelineConstructionType));
6413 
6414         // Multisample resolve tests where a render area is less than an attachment size.
6415         multisampleTests->addChild(
6416             createMultisampleResolveRenderpassRenderAreaTests(testCtx, pipelineConstructionType));
6417 
6418         // VK_EXT_multisampled_render_to_single_sampled
6419         {
6420             multisampleTests->addChild(createMultisampledRenderToSingleSampledTests(testCtx, pipelineConstructionType));
6421             // Take advantage of the code for this extension's tests to add some normal multisampling tests
6422             multisampleTests->addChild(createMultisampledMiscTests(testCtx, pipelineConstructionType));
6423         }
6424     }
6425 
6426     // VK_EXT_sample_locations
6427     multisampleTests->addChild(
6428         createMultisampleSampleLocationsExtTests(testCtx, pipelineConstructionType, useFragmentShadingRate));
6429 
6430     // VK_AMD_mixed_attachment
6431     multisampleTests->addChild(
6432         createMultisampleMixedAttachmentSamplesTests(testCtx, pipelineConstructionType, useFragmentShadingRate));
6433 
6434     // Sample mask with and without vk_ext_post_depth_coverage
6435     {
6436         const vk::VkSampleCountFlagBits standardSamplesSet[] = {vk::VK_SAMPLE_COUNT_2_BIT, vk::VK_SAMPLE_COUNT_4_BIT,
6437                                                                 vk::VK_SAMPLE_COUNT_8_BIT, vk::VK_SAMPLE_COUNT_16_BIT};
6438 
6439         TestCaseGroupPtr sampleMaskWithDepthTestGroup(new tcu::TestCaseGroup(testCtx, "sample_mask_with_depth_test"));
6440 
6441         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(standardSamplesSet); ++ndx)
6442         {
6443             std::ostringstream caseName;
6444             caseName << "samples_" << standardSamplesSet[ndx];
6445 
6446             sampleMaskWithDepthTestGroup->addChild(
6447                 new SampleMaskWithDepthTestTest(testCtx, caseName.str(), pipelineConstructionType,
6448                                                 standardSamplesSet[ndx], false, useFragmentShadingRate));
6449 
6450             caseName << "_post_depth_coverage";
6451             sampleMaskWithDepthTestGroup->addChild(
6452                 new SampleMaskWithDepthTestTest(testCtx, caseName.str(), pipelineConstructionType,
6453                                                 standardSamplesSet[ndx], true, useFragmentShadingRate));
6454         }
6455         multisampleTests->addChild(sampleMaskWithDepthTestGroup.release());
6456     }
6457 #endif // CTS_USES_VULKANSC
6458 
6459     // Input attachments are not supported with dynamic rendering and shader objects
6460     if (!isConstructionTypeShaderObject(pipelineConstructionType))
6461     {
6462         //Conservative rasterization test
6463         struct TestConfig
6464         {
6465             const char *name;
6466             bool enableMinSampleShading;
6467             const float minSampleShading;
6468             const bool enableSampleMask;
6469             VkSampleMask sampleMask;
6470             bool enablePostDepthCoverage;
6471         };
6472 
6473         const TestConfig testConfigs[] = {
6474             // Only conservative rendering applied
6475             {"plain_conservative", false, 0.0f, false, 0x0, false},
6476             // Post depth coverage enabled
6477             {"post_depth_coverage", false, 0.0f, false, 0x0, true},
6478             // minSampleMask set to 0.25f
6479             {"min_0_25", true, 0.25f, false, 0x0, false},
6480             // minSampleMask set to 0.5f
6481             {"min_0_5", true, 0.5f, false, 0x0, false},
6482             // minSampleMask set to 0.75f
6483             {"min_0_75", true, 0.75f, false, 0x0, false},
6484             // minSampleMask set to 1.0f
6485             {"min_0_1_0", true, 1.0f, false, 0x0, false},
6486             // All mask bits are on
6487             {"mask_all_off", false, 0.0f, true, 0x0, false},
6488             // All mask bits are off
6489             {"mask_all_on", false, 0.0f, true, 0xFFFFFFFF, false},
6490             // All mask elements are 0xAAAAAAAA
6491             {"mask_half_on", false, 0.0f, true, 0xAAAAAAAA, false},
6492         };
6493 
6494         const vk::VkSampleCountFlagBits standardSamplesSet[] = {vk::VK_SAMPLE_COUNT_2_BIT, vk::VK_SAMPLE_COUNT_4_BIT,
6495                                                                 vk::VK_SAMPLE_COUNT_8_BIT, vk::VK_SAMPLE_COUNT_16_BIT};
6496 
6497         enum vk::VkConservativeRasterizationModeEXT rasterizationMode[] = {
6498             vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,
6499             vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT};
6500 
6501         // Conservative rendering
6502         TestCaseGroupPtr conservativeGroup(new tcu::TestCaseGroup(testCtx, "conservative_with_full_coverage"));
6503 
6504         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(rasterizationMode); ++modeNdx)
6505         {
6506             const char *modeName = (modeNdx == 0 ? "overestimate" : "underestimate");
6507             TestCaseGroupPtr modesGroup(new tcu::TestCaseGroup(testCtx, modeName));
6508 
6509             for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(standardSamplesSet); ++samplesNdx)
6510             {
6511                 std::string caseName = "samples_" + std::to_string(standardSamplesSet[samplesNdx]) + "_";
6512 
6513                 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6514                 {
6515                     const TestConfig &testConfig = testConfigs[configNdx];
6516 
6517                     modesGroup->addChild(new SampleMaskWithConservativeTest(
6518                         testCtx, caseName + testConfig.name, pipelineConstructionType, standardSamplesSet[samplesNdx],
6519                         rasterizationMode[modeNdx], testConfig.enableMinSampleShading, testConfig.minSampleShading,
6520                         testConfig.enableSampleMask, testConfig.sampleMask, testConfig.enablePostDepthCoverage,
6521                         useFragmentShadingRate));
6522                 }
6523             }
6524 
6525             conservativeGroup->addChild(modesGroup.release());
6526         }
6527 
6528         multisampleTests->addChild(conservativeGroup.release());
6529     }
6530 
6531     {
6532         static const std::vector<vk::VkSampleCountFlagBits> kSampleCounts = {
6533             vk::VK_SAMPLE_COUNT_1_BIT,  vk::VK_SAMPLE_COUNT_2_BIT,  vk::VK_SAMPLE_COUNT_4_BIT,
6534             vk::VK_SAMPLE_COUNT_8_BIT,  vk::VK_SAMPLE_COUNT_16_BIT, vk::VK_SAMPLE_COUNT_32_BIT,
6535             vk::VK_SAMPLE_COUNT_64_BIT,
6536         };
6537 
6538         static const std::array<bool, 2> unusedAttachmentFlag = {{false, true}};
6539 
6540         {
6541             // Tests for multisample variable rate in subpasses
6542             TestCaseGroupPtr variableRateGroup(new tcu::TestCaseGroup(testCtx, "variable_rate"));
6543 
6544             // 2 and 3 subpasses should be good enough.
6545             static const std::vector<size_t> combinationSizes = {2, 3};
6546 
6547             // Basic cases.
6548             for (const auto size : combinationSizes)
6549             {
6550                 const auto combs = combinations(kSampleCounts, size);
6551                 for (const auto &comb : combs)
6552                 {
6553                     // Check sample counts actually vary between some of the subpasses.
6554                     std::set<vk::VkSampleCountFlagBits> uniqueVals(begin(comb), end(comb));
6555                     if (uniqueVals.size() < 2)
6556                         continue;
6557 
6558                     std::ostringstream name;
6559 
6560                     bool first = true;
6561                     for (const auto &count : comb)
6562                     {
6563                         name << (first ? "" : "_") << count;
6564                         first = false;
6565                     }
6566 
6567                     const VariableRateTestCase::TestParams params = {
6568                         pipelineConstructionType,  // PipelineConstructionType pipelineConstructionType;
6569                         false,                     // bool nonEmptyFramebuffer;
6570                         vk::VK_SAMPLE_COUNT_1_BIT, // vk::VkSampleCountFlagBits fbCount;
6571                         false,                     // bool unusedAttachment;
6572                         comb,                      // SampleCounts subpassCounts;
6573                         useFragmentShadingRate,    // bool useFragmentShadingRate;
6574                     };
6575                     variableRateGroup->addChild(new VariableRateTestCase(testCtx, name.str(), params));
6576                 }
6577             }
6578 
6579             // Cases with non-empty framebuffers: only 2 subpasses to avoid a large number of combinations.
6580             {
6581                 // Use one more sample count for the framebuffer attachment. It will be taken from the last item.
6582                 auto combs = combinations(kSampleCounts, 2 + 1);
6583                 for (auto &comb : combs)
6584                 {
6585                     // Framebuffer sample count.
6586                     const auto fbCount = comb.back();
6587                     comb.pop_back();
6588 
6589                     // Check sample counts actually vary between some of the subpasses.
6590                     std::set<vk::VkSampleCountFlagBits> uniqueVals(begin(comb), end(comb));
6591                     if (uniqueVals.size() < 2)
6592                         continue;
6593 
6594                     for (const auto flag : unusedAttachmentFlag)
6595                     {
6596                         std::ostringstream name;
6597 
6598                         bool first = true;
6599                         for (const auto &count : comb)
6600                         {
6601                             name << (first ? "" : "_") << count;
6602                             first = false;
6603                         }
6604 
6605                         name << "_fb_" << fbCount;
6606 
6607                         if (flag)
6608                         {
6609                             name << "_unused";
6610                         }
6611 
6612                         const VariableRateTestCase::TestParams params = {
6613                             pipelineConstructionType, // PipelineConstructionType pipelineConstructionType;
6614                             true,                     // bool nonEmptyFramebuffer;
6615                             fbCount,                  // vk::VkSampleCountFlagBits fbCount;
6616                             flag,                     // bool unusedAttachment;
6617                             comb,                     // SampleCounts subpassCounts;
6618                             useFragmentShadingRate,   // bool useFragmentShadingRate;
6619                         };
6620                         variableRateGroup->addChild(new VariableRateTestCase(testCtx, name.str(), params));
6621                     }
6622                 }
6623             }
6624 
6625             multisampleTests->addChild(variableRateGroup.release());
6626         }
6627 
6628         {
6629             // Tests for mixed sample count in empty subpass and framebuffer
6630             TestCaseGroupPtr mixedCountGroup(new tcu::TestCaseGroup(testCtx, "mixed_count"));
6631 
6632             const auto combs = combinations(kSampleCounts, 2);
6633             for (const auto &comb : combs)
6634             {
6635                 // Check different sample count.
6636                 DE_ASSERT(comb.size() == 2u);
6637                 const auto &fbCount    = comb[0];
6638                 const auto &emptyCount = comb[1];
6639 
6640                 if (fbCount == emptyCount)
6641                     continue;
6642 
6643                 const std::string fbCountStr    = de::toString(fbCount);
6644                 const std::string emptyCountStr = de::toString(emptyCount);
6645 
6646                 for (const auto flag : unusedAttachmentFlag)
6647                 {
6648                     const std::string nameSuffix = (flag ? "unused" : "");
6649                     const std::string descSuffix =
6650                         (flag ? "one unused attachment reference" : "no attachment references");
6651                     const std::string name =
6652                         fbCountStr + "_" + emptyCountStr + (nameSuffix.empty() ? "" : "_") + nameSuffix;
6653 
6654                     const VariableRateTestCase::TestParams params{
6655                         pipelineConstructionType, // PipelineConstructionType pipelineConstructionType;
6656                         true,                     // bool nonEmptyFramebuffer;
6657                         fbCount,                  // vk::VkSampleCountFlagBits fbCount;
6658                         flag,                     // bool unusedAttachment;
6659                         VariableRateTestCase::SampleCounts(1u,
6660                                                            emptyCount), // SampleCounts subpassCounts;
6661                         useFragmentShadingRate,                         // bool useFragmentShadingRate;
6662                     };
6663                     mixedCountGroup->addChild(new VariableRateTestCase(testCtx, name, params));
6664                 }
6665             }
6666 
6667             multisampleTests->addChild(mixedCountGroup.release());
6668         }
6669 
6670         if (!useFragmentShadingRate)
6671         {
6672             // Tests using alpha to coverage combined with depth/stencil/mask writes in the frag shader
6673             TestCaseGroupPtr zExportGroup(new tcu::TestCaseGroup(testCtx, "z_export"));
6674 
6675             const struct
6676             {
6677                 ZExportFlags flags;
6678                 const char *name;
6679             } flagsCases[] = {
6680                 {(ZEXP_DEPTH_BIT), "depth"},
6681                 {(ZEXP_STENCIL_BIT), "stencil"},
6682                 {(ZEXP_SAMPLE_MASK_BIT), "sample_mask"},
6683                 {(ZEXP_DEPTH_BIT | ZEXP_STENCIL_BIT), "depth_stencil"},
6684                 {(ZEXP_DEPTH_BIT | ZEXP_STENCIL_BIT | ZEXP_SAMPLE_MASK_BIT), "write_all"},
6685             };
6686 
6687             for (const auto &flagsCase : flagsCases)
6688             {
6689                 for (const bool dynamicAlphaToCoverage : {false, true})
6690                     for (const bool dynamicRendering : {false, true})
6691                     {
6692 #ifdef CTS_USES_VULKANSC
6693                         if (dynamicAlphaToCoverage || dynamicRendering)
6694                             continue;
6695 #endif // CTS_USES_VULKANSC
6696                         if (dynamicRendering && !isConstructionTypeLibrary(pipelineConstructionType))
6697                             continue;
6698 
6699                         const auto testName = std::string(flagsCase.name) + "_" +
6700                                               (dynamicAlphaToCoverage ? "dynamic" : "static") +
6701                                               "_atc" // atc = alpha to coverage
6702                                               + (dynamicRendering ? "_dynamic_rendering" : "");
6703                         const ZExportParams params(pipelineConstructionType, flagsCase.flags, dynamicAlphaToCoverage,
6704                                                    dynamicRendering);
6705 
6706                         addFunctionCaseWithPrograms(zExportGroup.get(), testName, ZExportCheckSupport,
6707                                                     ZExportInitPrograms, ZExportIterate, params);
6708                     }
6709             }
6710 
6711             multisampleTests->addChild(zExportGroup.release());
6712         }
6713     }
6714 
6715     return multisampleTests.release();
6716 }
6717 
6718 } // namespace pipeline
6719 } // namespace vkt
6720