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