1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Advanced Micro Devices, Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Tests for VK_AMD_mixed_attachment_samples
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineMultisampleMixedAttachmentSamplesTests.hpp"
28 #include "vktPipelineSampleLocationsUtil.hpp"
29 #include "vktPipelineMakeUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vktTestGroupUtil.hpp"
33 
34 #include "vkCmdUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkPlatform.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkBuilderUtil.hpp"
42 #include "vkPrograms.hpp"
43 #include "vkImageUtil.hpp"
44 
45 #include "deUniquePtr.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deRandom.hpp"
48 #include "deMath.h"
49 
50 #include "tcuVector.hpp"
51 #include "tcuTestLog.hpp"
52 #include "tcuImageCompare.hpp"
53 #include "tcuTextureUtil.hpp"
54 #include "tcuRGBA.hpp"
55 
56 #include <string>
57 #include <vector>
58 
59 namespace vkt
60 {
61 namespace pipeline
62 {
63 namespace
64 {
65 using namespace vk;
66 using de::MovePtr;
67 using de::SharedPtr;
68 using de::UniquePtr;
69 using tcu::UVec2;
70 using tcu::Vec2;
71 using tcu::Vec4;
72 
compareGreenImage(tcu::TestLog & log,const char * name,const char * description,const tcu::ConstPixelBufferAccess & image)73 bool compareGreenImage(tcu::TestLog &log, const char *name, const char *description,
74                        const tcu::ConstPixelBufferAccess &image)
75 {
76     tcu::TextureLevel greenImage(image.getFormat(), image.getWidth(), image.getHeight());
77     tcu::clear(greenImage.getAccess(), tcu::RGBA::green().toIVec());
78     return tcu::intThresholdCompare(log, name, description, greenImage.getAccess(), image, tcu::UVec4(2u),
79                                     tcu::COMPARE_LOG_RESULT);
80 }
81 
getImageAspectFlags(const VkFormat format)82 VkImageAspectFlags getImageAspectFlags(const VkFormat format)
83 {
84     const tcu::TextureFormat tcuFormat = mapVkFormat(format);
85 
86     if (tcuFormat.order == tcu::TextureFormat::DS)
87         return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
88     else if (tcuFormat.order == tcu::TextureFormat::D)
89         return VK_IMAGE_ASPECT_DEPTH_BIT;
90     else if (tcuFormat.order == tcu::TextureFormat::S)
91         return VK_IMAGE_ASPECT_STENCIL_BIT;
92 
93     DE_ASSERT(false);
94     return 0u;
95 }
96 
97 struct CompareData
98 {
99     Vec4 color;
100     float depth;
101     uint32_t stencil;
102 
103     // Pad to 2*16 bytes, in the shader the base alignment of this structure is 16 due to vec4
104     uint32_t padding[2];
105 
CompareDatavkt::pipeline::__anon7e964aba0111::CompareData106     CompareData() : color(Vec4(0.0f)), depth(0.0f), stencil(0u)
107     {
108         padding[0] = 0u;
109         padding[1] = 0u;
110 
111         static_assert(sizeof(CompareData) == (2 * 16), "Wrong structure size, expected 16 bytes");
112     }
113 };
114 
115 //! Make a (unused) sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)116 Move<VkSampler> makeSampler(const DeviceInterface &vk, const VkDevice device)
117 {
118     const VkSamplerCreateInfo samplerParams = {
119         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType         sType;
120         DE_NULL,                                 // const void*             pNext;
121         (VkSamplerCreateFlags)0,                 // VkSamplerCreateFlags    flags;
122         VK_FILTER_NEAREST,                       // VkFilter                magFilter;
123         VK_FILTER_NEAREST,                       // VkFilter                minFilter;
124         VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode     mipmapMode;
125         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode    addressModeU;
126         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode    addressModeV;
127         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode    addressModeW;
128         0.0f,                                    // float                   mipLodBias;
129         VK_FALSE,                                // VkBool32                anisotropyEnable;
130         1.0f,                                    // float                   maxAnisotropy;
131         VK_FALSE,                                // VkBool32                compareEnable;
132         VK_COMPARE_OP_ALWAYS,                    // VkCompareOp             compareOp;
133         0.0f,                                    // float                   minLod;
134         0.0f,                                    // float                   maxLod;
135         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor           borderColor;
136         VK_FALSE,                                // VkBool32                unnormalizedCoordinates;
137     };
138     return createSampler(vk, device, &samplerParams);
139 }
140 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const UVec2 & size,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)141 Move<VkImage> makeImage(const DeviceInterface &vk, const VkDevice device, const VkFormat format, const UVec2 &size,
142                         const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
143 {
144     const VkImageCreateInfo imageParams = {
145         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
146         DE_NULL,                             // const void* pNext;
147         (VkImageCreateFlags)0,               // VkImageCreateFlags flags;
148         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
149         format,                              // VkFormat format;
150         makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
151         1u,                                  // uint32_t mipLevels;
152         1u,                                  // uint32_t arrayLayers;
153         samples,                             // VkSampleCountFlagBits samples;
154         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
155         usage,                               // VkImageUsageFlags usage;
156         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
157         0u,                                  // uint32_t queueFamilyIndexCount;
158         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
159         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
160     };
161     return createImage(vk, device, &imageParams);
162 }
163 
isDepthFormat(const VkFormat format)164 inline bool isDepthFormat(const VkFormat format)
165 {
166     return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
167 }
168 
isStencilFormat(const VkFormat format)169 inline bool isStencilFormat(const VkFormat format)
170 {
171     return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
172 }
173 
174 //! Create a test-specific MSAA pipeline
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertexModule,const ShaderWrapper fragmentModule,const bool useVertexInput,const uint32_t subpassNdx,const UVec2 & renderSize,const VkImageAspectFlags depthStencilAspect,const VkSampleCountFlagBits numSamples,const bool sampleShadingEnable,const bool useFragmentShadingRate,const VkSampleLocationsInfoEXT * pSampleLocationsInfo=DE_NULL)175 void preparePipelineWrapper(
176     GraphicsPipelineWrapper &gpw, const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
177     const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const bool useVertexInput,
178     const uint32_t subpassNdx, const UVec2 &renderSize,
179     const VkImageAspectFlags depthStencilAspect, //!< Used to determine which D/S tests to turn on
180     const VkSampleCountFlagBits numSamples, const bool sampleShadingEnable, const bool useFragmentShadingRate,
181     const VkSampleLocationsInfoEXT *pSampleLocationsInfo = DE_NULL)
182 {
183     std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
184     std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
185 
186     // Vertex attributes: position and color
187     if (useVertexInput)
188     {
189         vertexInputBindingDescriptions.push_back(
190             makeVertexInputBindingDescription(0u, 2 * sizeof(Vec4), VK_VERTEX_INPUT_RATE_VERTEX));
191         vertexInputAttributeDescriptions.push_back(
192             makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
193         vertexInputAttributeDescriptions.push_back(
194             makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(Vec4)));
195     }
196 
197     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
198         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,    // VkStructureType sType;
199         DE_NULL,                                                      // const void* pNext;
200         (VkPipelineVertexInputStateCreateFlags)0,                     // VkPipelineVertexInputStateCreateFlags flags;
201         static_cast<uint32_t>(vertexInputBindingDescriptions.size()), // uint32_t vertexBindingDescriptionCount;
202         dataOrNullPtr(
203             vertexInputBindingDescriptions), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
204         static_cast<uint32_t>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount;
205         dataOrNullPtr(
206             vertexInputAttributeDescriptions), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
207     };
208 
209     const std::vector<VkViewport> viewport{makeViewport(renderSize.x(), renderSize.y())};
210     const std::vector<VkRect2D> scissor{makeRect2D(renderSize.x(), renderSize.y())};
211 
212     VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo = {
213         VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT, // VkStructureType             sType;
214         DE_NULL,                                                           // const void*                 pNext;
215         VK_TRUE,                    // VkBool32                    sampleLocationsEnable;
216         VkSampleLocationsInfoEXT(), // VkSampleLocationsInfoEXT    sampleLocationsInfo;
217     };
218 
219     VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
220         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
221         DE_NULL,                                                  // const void* pNext;
222         (VkPipelineMultisampleStateCreateFlags)0,                 // VkPipelineMultisampleStateCreateFlags flags;
223         numSamples,                                               // VkSampleCountFlagBits rasterizationSamples;
224         sampleShadingEnable,                                      // VkBool32 sampleShadingEnable;
225         1.0f,                                                     // float minSampleShading;
226         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
227         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
228         VK_FALSE                                                  // VkBool32 alphaToOneEnable;
229     };
230 
231     if (pSampleLocationsInfo)
232     {
233         pipelineSampleLocationsCreateInfo.sampleLocationsInfo = *pSampleLocationsInfo;
234         pipelineMultisampleStateInfo.pNext                    = &pipelineSampleLocationsCreateInfo;
235     }
236 
237     // Simply increment the buffer
238     const VkStencilOpState stencilOpState =
239         makeStencilOpState(VK_STENCIL_OP_KEEP,                // stencil fail
240                            VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass
241                            VK_STENCIL_OP_KEEP,                // depth only fail
242                            VK_COMPARE_OP_ALWAYS,              // compare op
243                            ~0u,                               // compare mask
244                            ~0u,                               // write mask
245                            0u);                               // reference
246 
247     // Always pass the depth test
248     VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
249         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
250         DE_NULL,                                                    // const void* pNext;
251         (VkPipelineDepthStencilStateCreateFlags)0,                  // VkPipelineDepthStencilStateCreateFlags flags;
252         (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0u,     // VkBool32 depthTestEnable;
253         VK_TRUE,                                                    // VkBool32 depthWriteEnable;
254         VK_COMPARE_OP_ALWAYS,                                       // VkCompareOp depthCompareOp;
255         VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
256         (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0u,   // VkBool32 stencilTestEnable;
257         stencilOpState,                                             // VkStencilOpState front;
258         stencilOpState,                                             // VkStencilOpState back;
259         0.0f,                                                       // float minDepthBounds;
260         1.0f,                                                       // float maxDepthBounds;
261     };
262 
263     const VkColorComponentFlags colorComponentsAll =
264         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
265     const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState = {
266         VK_FALSE,             // VkBool32 blendEnable;
267         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcColorBlendFactor;
268         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
269         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
270         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcAlphaBlendFactor;
271         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
272         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
273         colorComponentsAll,   // VkColorComponentFlags colorWriteMask;
274     };
275 
276     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
277         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
278         DE_NULL,                                                  // const void* pNext;
279         (VkPipelineColorBlendStateCreateFlags)0,                  // VkPipelineColorBlendStateCreateFlags flags;
280         VK_FALSE,                                                 // VkBool32 logicOpEnable;
281         VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
282         1u,                                                       // uint32_t attachmentCount;
283         &defaultBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
284         {0.0f, 0.0f, 0.0f, 0.0f},     // float blendConstants[4];
285     };
286 
287     VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo{
288         VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
289         DE_NULL,                                                                // const void* pNext;
290         {2, 2},                                                                 // VkExtent2D fragmentSize;
291         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
292          VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
293     };
294 
295     gpw.setDefaultRasterizationState()
296         .setupVertexInputState(&vertexInputStateInfo)
297         .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, renderPass, subpassNdx, vertexModule,
298                                           nullptr, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL,
299                                           (useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr))
300         .setupFragmentShaderState(pipelineLayout, renderPass, subpassNdx, fragmentModule,
301                                   &pipelineDepthStencilStateInfo, &pipelineMultisampleStateInfo)
302         .setupFragmentOutputState(renderPass, subpassNdx, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
303         .setMonolithicPipelineLayout(pipelineLayout)
304         .buildPipeline();
305 }
306 
307 //! Wrap float after an increment
wrapIncFloat(float a,float min,float max)308 inline float wrapIncFloat(float a, float min, float max)
309 {
310     return deFloatMax(min, deFloatMod(a, max));
311 }
312 
313 //! Generate expected data for color, depth, and stencil samples of a given image.
314 //! Samples are ordered starting at pixel (0, 0) - see compute shader source for reference.
generateCompareData(const uint32_t seed,const UVec2 & imageSize,const uint32_t numCoverageSamples,const uint32_t numColorSamples,const uint32_t numDepthStencilSamples)315 std::vector<CompareData> generateCompareData(const uint32_t seed, const UVec2 &imageSize,
316                                              const uint32_t numCoverageSamples, const uint32_t numColorSamples,
317                                              const uint32_t numDepthStencilSamples)
318 {
319     std::vector<CompareData> allData;
320     de::Random rng(seed);
321 
322     for (uint32_t y = 0u; y < imageSize.y(); ++y)
323         for (uint32_t x = 0u; x < imageSize.x(); ++x)
324             for (uint32_t sample = 0u; sample < numCoverageSamples; ++sample)
325             {
326                 CompareData cd;
327 
328                 if (sample < numColorSamples)
329                 {
330                     for (int i = 0; i < 3; ++i)
331                         cd.color[i] = 0.1f * static_cast<float>(rng.getInt(1, 10));
332 
333                     cd.color.w() = 1.0f;
334                 }
335 
336                 if (sample < numDepthStencilSamples)
337                 {
338                     const uint32_t globalSample = sample + numColorSamples * (x + imageSize.x() * y);
339                     cd.depth   = wrapIncFloat(0.05f * static_cast<float>(1 + globalSample), 0.05f, 1.0f);
340                     cd.stencil = 1 + globalSample % numCoverageSamples;
341                 }
342 
343                 allData.push_back(cd);
344             }
345 
346     return allData;
347 }
348 
349 //! NDC transformation algorithm for sample locations
350 template <typename SampleAccessor>
ndcTransformEachSampleInPixel(const UVec2 & framebufferSize,const uint32_t numSamplesPerPixel,const SampleAccessor & access)351 std::vector<Vec2> ndcTransformEachSampleInPixel(const UVec2 &framebufferSize, const uint32_t numSamplesPerPixel,
352                                                 const SampleAccessor &access)
353 {
354     std::vector<Vec2> locations;
355 
356     for (uint32_t y = 0; y < framebufferSize.y(); ++y)
357         for (uint32_t x = 0; x < framebufferSize.x(); ++x)
358             for (uint32_t sampleNdx = 0; sampleNdx < numSamplesPerPixel; ++sampleNdx)
359             {
360                 const Vec2 &sp      = access(x, y, sampleNdx);
361                 const float globalX = sp.x() + static_cast<float>(x);
362                 const float globalY = sp.y() + static_cast<float>(y);
363 
364                 // Transform to [-1, 1] space
365                 locations.push_back(Vec2(-1.0f + 2.0f * (globalX / static_cast<float>(framebufferSize.x())),
366                                          -1.0f + 2.0f * (globalY / static_cast<float>(framebufferSize.y()))));
367             }
368 
369     return locations;
370 }
371 
372 class AccessStandardSampleLocationsArray
373 {
374 public:
AccessStandardSampleLocationsArray(const Vec2 * ptr)375     AccessStandardSampleLocationsArray(const Vec2 *ptr) : m_pData(ptr)
376     {
377     }
378 
operator ()(const uint32_t x,const uint32_t y,const uint32_t sampleNdx) const379     const Vec2 &operator()(const uint32_t x, const uint32_t y, const uint32_t sampleNdx) const
380     {
381         DE_UNREF(x);
382         DE_UNREF(y);
383         return m_pData[sampleNdx];
384     }
385 
386 private:
387     const Vec2 *m_pData;
388 };
389 
390 class AccessMultisamplePixelGrid
391 {
392 public:
AccessMultisamplePixelGrid(const MultisamplePixelGrid * ptr)393     AccessMultisamplePixelGrid(const MultisamplePixelGrid *ptr) : m_pGrid(ptr)
394     {
395     }
396 
operator ()(const uint32_t x,const uint32_t y,const uint32_t sampleNdx) const397     Vec2 operator()(const uint32_t x, const uint32_t y, const uint32_t sampleNdx) const
398     {
399         const VkSampleLocationEXT &sp = m_pGrid->getSample(x, y, sampleNdx);
400         return Vec2(sp.x, sp.y);
401     }
402 
403 private:
404     const MultisamplePixelGrid *m_pGrid;
405 };
406 
407 //! Generate NDC space standard sample locations at each framebuffer pixel
408 //! Data is filled starting at pixel (0,0) and for each pixel there are numSamples samples
genFramebufferStandardSampleLocations(const VkSampleCountFlagBits numSamples,const UVec2 & framebufferSize)409 std::vector<Vec2> genFramebufferStandardSampleLocations(const VkSampleCountFlagBits numSamples,
410                                                         const UVec2 &framebufferSize)
411 {
412     static const Vec2 s_location_samples_1[] = {
413         Vec2(0.5f, 0.5f),
414     };
415     static const Vec2 s_location_samples_2[] = {
416         Vec2(0.75f, 0.75f),
417         Vec2(0.25f, 0.25f),
418     };
419     static const Vec2 s_location_samples_4[] = {
420         Vec2(0.375f, 0.125f),
421         Vec2(0.875f, 0.375f),
422         Vec2(0.125f, 0.625f),
423         Vec2(0.625f, 0.875f),
424     };
425     static const Vec2 s_location_samples_8[] = {
426         Vec2(0.5625f, 0.3125f), Vec2(0.4375f, 0.6875f), Vec2(0.8125f, 0.5625f), Vec2(0.3125f, 0.1875f),
427         Vec2(0.1875f, 0.8125f), Vec2(0.0625f, 0.4375f), Vec2(0.6875f, 0.9375f), Vec2(0.9375f, 0.0625f),
428     };
429     static const Vec2 s_location_samples_16[] = {
430         Vec2(0.5625f, 0.5625f), Vec2(0.4375f, 0.3125f), Vec2(0.3125f, 0.6250f), Vec2(0.7500f, 0.4375f),
431         Vec2(0.1875f, 0.3750f), Vec2(0.6250f, 0.8125f), Vec2(0.8125f, 0.6875f), Vec2(0.6875f, 0.1875f),
432         Vec2(0.3750f, 0.8750f), Vec2(0.5000f, 0.0625f), Vec2(0.2500f, 0.1250f), Vec2(0.1250f, 0.7500f),
433         Vec2(0.0000f, 0.5000f), Vec2(0.9375f, 0.2500f), Vec2(0.8750f, 0.9375f), Vec2(0.0625f, 0.0000f),
434     };
435 
436     const Vec2 *pSampleLocation = DE_NULL;
437 
438     switch (numSamples)
439     {
440     case VK_SAMPLE_COUNT_1_BIT:
441         pSampleLocation = s_location_samples_1;
442         break;
443     case VK_SAMPLE_COUNT_2_BIT:
444         pSampleLocation = s_location_samples_2;
445         break;
446     case VK_SAMPLE_COUNT_4_BIT:
447         pSampleLocation = s_location_samples_4;
448         break;
449     case VK_SAMPLE_COUNT_8_BIT:
450         pSampleLocation = s_location_samples_8;
451         break;
452     case VK_SAMPLE_COUNT_16_BIT:
453         pSampleLocation = s_location_samples_16;
454         break;
455 
456     default:
457         DE_ASSERT(0);
458         return std::vector<Vec2>();
459     }
460 
461     return ndcTransformEachSampleInPixel(framebufferSize, static_cast<uint32_t>(numSamples),
462                                          AccessStandardSampleLocationsArray(pSampleLocation));
463 }
464 
465 //! Generate NDC space custom sample locations at each framebuffer pixel, based on the given pixel grid
getSampleLocations(const MultisamplePixelGrid & pixelGrid,const UVec2 & framebufferSize)466 std::vector<Vec2> getSampleLocations(const MultisamplePixelGrid &pixelGrid, const UVec2 &framebufferSize)
467 {
468     return ndcTransformEachSampleInPixel(framebufferSize, pixelGrid.samplesPerPixel(),
469                                          AccessMultisamplePixelGrid(&pixelGrid));
470 }
471 
472 struct PositionColor
473 {
474     tcu::Vec4 position;
475     tcu::Vec4 color;
476 
PositionColorvkt::pipeline::__anon7e964aba0111::PositionColor477     PositionColor(const tcu::Vec4 &pos, const tcu::Vec4 &col) : position(pos), color(col)
478     {
479     }
480 };
481 
482 //! Generate subpixel triangles containing the sample position, based on compare data.
483 //! Stencil values are created by overlapping triangles, so the stencil pipeline state must be set up accordingly.
generateSubpixelTriangles(const UVec2 & renderSize,const std::vector<CompareData> & compareData,const std::vector<Vec2> & sampleLocations)484 std::vector<PositionColor> generateSubpixelTriangles(const UVec2 &renderSize,
485                                                      const std::vector<CompareData> &compareData,
486                                                      const std::vector<Vec2> &sampleLocations)
487 {
488     std::vector<PositionColor> vertices;
489 
490     // For each sample location (in the whole framebuffer), create a sub-pixel triangle that contains it.
491     // NDC viewport size is 2.0 in X and Y and NDC pixel width/height depends on the framebuffer resolution.
492     const Vec2 pixelSize = Vec2(2.0f) / renderSize.cast<float>();
493     const Vec2 offset    = pixelSize / 16.0f; // 4 bits precision
494 
495     // Surround with a roughly centered triangle
496     const float y1 = 0.5f * offset.y();
497     const float y2 = 0.35f * offset.y();
498     const float x1 = 0.5f * offset.x();
499 
500     DE_ASSERT(compareData.size() == sampleLocations.size());
501 
502     for (std::size_t globalSampleNdx = 0; globalSampleNdx < sampleLocations.size(); ++globalSampleNdx)
503     {
504         const Vec2 &loc       = sampleLocations[globalSampleNdx];
505         const CompareData &cd = compareData[globalSampleNdx];
506 
507         // Overdraw at the same position to get the desired stencil
508         // Draw at least once, if stencil is 0
509         for (uint32_t i = 0; i < deMaxu32(1u, cd.stencil); ++i)
510         {
511             vertices.push_back(PositionColor(Vec4(loc.x(), loc.y() - y1, cd.depth, 1.0f), cd.color));
512             vertices.push_back(PositionColor(Vec4(loc.x() - x1, loc.y() + y2, cd.depth, 1.0f), cd.color));
513             vertices.push_back(PositionColor(Vec4(loc.x() + x1, loc.y() + y2, cd.depth, 1.0f), cd.color));
514         }
515     }
516 
517     return vertices;
518 }
519 
reportSampleError(tcu::TestLog & log,const std::string & sampleDesc,UVec2 & renderSize,const uint32_t numCoverageSamples,const uint32_t globalSampleNdx)520 void reportSampleError(tcu::TestLog &log, const std::string &sampleDesc, UVec2 &renderSize,
521                        const uint32_t numCoverageSamples, const uint32_t globalSampleNdx)
522 {
523     const uint32_t pixelNdx = globalSampleNdx / numCoverageSamples;
524     const uint32_t x        = pixelNdx % renderSize.x();
525     const uint32_t y        = pixelNdx / renderSize.x();
526     const uint32_t sample   = globalSampleNdx % numCoverageSamples;
527 
528     log << tcu::TestLog::Message << "Incorrect " << sampleDesc << " sample (" << sample << ") at pixel (" << x << ", "
529         << y << ")" << tcu::TestLog::EndMessage;
530 }
531 
checkSampleRequirements(Context & context,const VkSampleCountFlagBits numColorSamples,const VkSampleCountFlagBits numDepthStencilSamples,const bool requireStandardSampleLocations)532 void checkSampleRequirements(Context &context, const VkSampleCountFlagBits numColorSamples,
533                              const VkSampleCountFlagBits numDepthStencilSamples,
534                              const bool requireStandardSampleLocations)
535 {
536     const VkPhysicalDeviceLimits &limits = context.getDeviceProperties().limits;
537 
538     if ((limits.framebufferColorSampleCounts & numColorSamples) == 0u)
539         TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
540 
541     if ((limits.framebufferDepthSampleCounts & numDepthStencilSamples) == 0u)
542         TCU_THROW(NotSupportedError, "framebufferDepthSampleCounts: sample count not supported");
543 
544     if ((limits.framebufferStencilSampleCounts & numDepthStencilSamples) == 0u)
545         TCU_THROW(NotSupportedError, "framebufferStencilSampleCounts: sample count not supported");
546 
547     if ((limits.sampledImageColorSampleCounts & numColorSamples) == 0u)
548         TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
549 
550     if ((limits.sampledImageDepthSampleCounts & numDepthStencilSamples) == 0u)
551         TCU_THROW(NotSupportedError, "sampledImageDepthSampleCounts: sample count not supported");
552 
553     if ((limits.sampledImageStencilSampleCounts & numDepthStencilSamples) == 0u)
554         TCU_THROW(NotSupportedError, "sampledImageStencilSampleCounts: sample count not supported");
555 
556     // This is required to output geometry that is covering a specific sample
557     if (requireStandardSampleLocations && !limits.standardSampleLocations)
558         TCU_THROW(NotSupportedError, "standardSampleLocations: not supported");
559 }
560 
checkImageRequirements(Context & context,const VkFormat format,const VkFormatFeatureFlags requiredFeatureFlags,const VkImageUsageFlags requiredUsageFlags,const VkSampleCountFlagBits requiredSampleCount=VK_SAMPLE_COUNT_1_BIT)561 void checkImageRequirements(Context &context, const VkFormat format, const VkFormatFeatureFlags requiredFeatureFlags,
562                             const VkImageUsageFlags requiredUsageFlags,
563                             const VkSampleCountFlagBits requiredSampleCount = VK_SAMPLE_COUNT_1_BIT)
564 {
565     const InstanceInterface &vki          = context.getInstanceInterface();
566     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
567     VkImageFormatProperties imageProperties;
568 
569     const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
570 
571     if ((formatProperties.optimalTilingFeatures & requiredFeatureFlags) != requiredFeatureFlags)
572         TCU_THROW(NotSupportedError, (de::toString(format) + ": format features not supported").c_str());
573 
574     const VkResult result =
575         vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
576                                                    requiredUsageFlags, (VkImageCreateFlags)0, &imageProperties);
577 
578     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
579         TCU_THROW(NotSupportedError, (de::toString(format) + ": format not supported").c_str());
580 
581     if ((imageProperties.sampleCounts & requiredSampleCount) != requiredSampleCount)
582         TCU_THROW(NotSupportedError, (de::toString(format) + ": sample count not supported").c_str());
583 }
584 
585 //! Used after a render pass color output (draw or resolve)
recordCopyOutputImageToBuffer(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const UVec2 & imageSize,const VkImage srcImage,const VkBuffer dstBuffer)586 void recordCopyOutputImageToBuffer(const DeviceInterface &vk, const VkCommandBuffer cmdBuffer, const UVec2 &imageSize,
587                                    const VkImage srcImage, const VkBuffer dstBuffer)
588 {
589     // Image read barrier after color output
590     {
591         const VkImageMemoryBarrier barrier = {
592             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType;
593             DE_NULL,                                // const void*                pNext;
594             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,   // VkAccessFlags              srcAccessMask;
595             VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags              dstAccessMask;
596             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout              oldLayout;
597             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout              newLayout;
598             VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   srcQueueFamilyIndex;
599             VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   dstQueueFamilyIndex;
600             srcImage,                               // VkImage                    image;
601             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
602                                       1u), // VkImageSubresourceRange    subresourceRange;
603         };
604 
605         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
606                               (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
607     }
608     // Resolve image -> host buffer
609     {
610         const VkBufferImageCopy region = {
611             0ull, // VkDeviceSize                bufferOffset;
612             0u,   // uint32_t                    bufferRowLength;
613             0u,   // uint32_t                    bufferImageHeight;
614             makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
615                                        1u),                 // VkImageSubresourceLayers    imageSubresource;
616             makeOffset3D(0, 0, 0),                          // VkOffset3D                  imageOffset;
617             makeExtent3D(imageSize.x(), imageSize.y(), 1u), // VkExtent3D                  imageExtent;
618         };
619 
620         vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, &region);
621     }
622     // Buffer write barrier
623     {
624         const VkBufferMemoryBarrier barrier = {
625             VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
626             DE_NULL,                                 // const void*        pNext;
627             VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags      srcAccessMask;
628             VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
629             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
630             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
631             dstBuffer,                               // VkBuffer           buffer;
632             0ull,                                    // VkDeviceSize       offset;
633             VK_WHOLE_SIZE,                           // VkDeviceSize       size;
634         };
635 
636         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
637                               (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
638     }
639 }
640 
641 namespace VerifySamples
642 {
643 
644 //! The parameters that define a test case
645 struct TestParams
646 {
647     struct SampleCount
648     {
649         VkSampleCountFlagBits numCoverageSamples; //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
650         VkSampleCountFlagBits numColorSamples;    //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
651         VkSampleCountFlagBits
652             numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
653     };
654 
655     PipelineConstructionType pipelineConstructionType; //!< The wya pipeline is constructed
656     VkFormat colorFormat;                              //!< Color attachment format
657     VkFormat depthStencilFormat;         //!< D/S attachment format. Will test both aspects if it's a mixed format
658     bool useProgrammableSampleLocations; //!< Try to use VK_EXT_sample_locations if available
659     bool useFragmentShadingRate;         //!< Try to use VK_KHR_fragment_shading_rate if available
660     std::vector<SampleCount> perSubpassSamples; //!< Will use multiple subpasses if more than one element
661 
TestParamsvkt::pipeline::__anon7e964aba0111::VerifySamples::TestParams662     TestParams(void) : colorFormat(), depthStencilFormat(), useProgrammableSampleLocations(), useFragmentShadingRate()
663     {
664     }
665 };
666 
667 //! Common data used by the test
668 struct WorkingData
669 {
670     struct PerSubpass
671     {
672         uint32_t numVertices; //!< Number of vertices defined in the vertex buffer
673         Move<VkBuffer> vertexBuffer;
674         MovePtr<Allocation> vertexBufferAlloc;
675         Move<VkImage> colorImage;         //!< Color image
676         Move<VkImageView> colorImageView; //!< Color attachment
677         MovePtr<Allocation> colorImageAlloc;
678         Move<VkImage> depthStencilImage;         //!< Depth stencil image
679         Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment
680         Move<VkImageView> depthOnlyImageView;    //!< Depth aspect for shader read
681         Move<VkImageView> stencilOnlyImageView;  //!< Stencil aspect for shader read
682         MovePtr<Allocation> depthStencilImageAlloc;
683         Move<VkBuffer> compareBuffer; //!< Buffer used to verify the images - comparison data
684         MovePtr<Allocation> compareBufferAlloc;
685         VkDeviceSize compareBufferSize;
686         Move<VkBuffer> resultBuffer; //!< Buffer used to verify the images - results
687         MovePtr<Allocation> resultBufferAlloc;
688         VkDeviceSize resultBufferSize;
689         uint32_t numResultElements;              //!< Number of checksums in the result buffer
690         MovePtr<MultisamplePixelGrid> pixelGrid; //!< Programmable locations
691 
PerSubpassvkt::pipeline::__anon7e964aba0111::VerifySamples::WorkingData::PerSubpass692         PerSubpass(void) : numVertices(), compareBufferSize(), resultBufferSize(), numResultElements()
693         {
694         }
695     };
696 
697     UVec2 renderSize;                                                       //!< Size of the framebuffer
698     VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties; //!< Used with VK_EXT_sample_locations
699 
700     std::vector<de::SharedPtr<PerSubpass>> perSubpass; //!< Test may use more than one set of data
701 
WorkingDatavkt::pipeline::__anon7e964aba0111::VerifySamples::WorkingData702     WorkingData(void) : sampleLocationsProperties()
703     {
704     }
705 };
706 
addVerificationComputeShader(SourceCollections & programCollection,const VkSampleCountFlagBits numCoverageSamples,const VkSampleCountFlagBits numColorSamples,const VkSampleCountFlagBits numDepthStencilSamples,const VkFormat depthStencilFormat,const std::string & nameSuffix)707 void addVerificationComputeShader(SourceCollections &programCollection, const VkSampleCountFlagBits numCoverageSamples,
708                                   const VkSampleCountFlagBits numColorSamples,
709                                   const VkSampleCountFlagBits numDepthStencilSamples, const VkFormat depthStencilFormat,
710                                   const std::string &nameSuffix)
711 {
712     const bool isColorMS         = (numColorSamples != VK_SAMPLE_COUNT_1_BIT);
713     const bool isDepthStencilMS  = (numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT);
714     const std::string colorBit   = de::toString(static_cast<uint32_t>(VK_IMAGE_ASPECT_COLOR_BIT)) + "u";
715     const std::string depthBit   = de::toString(static_cast<uint32_t>(VK_IMAGE_ASPECT_DEPTH_BIT)) + "u";
716     const std::string stencilBit = de::toString(static_cast<uint32_t>(VK_IMAGE_ASPECT_STENCIL_BIT)) + "u";
717 
718     std::ostringstream src;
719     src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
720         << "\n"
721         << "struct CompareData {\n"
722         << "    vec4  color;\n"
723         << "    float depth;\n"
724         << "    uint  stencil;\n"
725         << "};\n"
726         << "\n"
727         << "layout(local_size_x = " << static_cast<uint32_t>(numCoverageSamples)
728         << ") in;\n"
729         // Always use this descriptor layout and ignore unused bindings
730         << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
731         << "    uint values[];\n"
732         << "} sb_out;\n"
733         << "layout(set = 0, binding = 1, std430) readonly buffer InputCompare {\n"
734         << "    CompareData    data[];\n"
735         << "} sb_cmp;\n"
736         << "layout(set = 0, binding = 2) uniform sampler2D" << (isColorMS ? "MS" : "") << "  colorImage;\n"
737         << "layout(set = 0, binding = 3) uniform sampler2D" << (isDepthStencilMS ? "MS" : "") << "  depthImage;\n"
738         << "layout(set = 0, binding = 4) uniform usampler2D" << (isDepthStencilMS ? "MS" : "") << " stencilImage;\n"
739         << "\n"
740         << "void main (void)\n"
741         << "{\n"
742 
743         // Data for each sample in each pixel is laid out linearly (e.g 2 samples):
744         // [pixel(0, 0) sample(0)][pixel(0, 0) sample(1)][pixel(1, 0) sample(0)][pixel(1, 0) sample(1)]...
745 
746         << "    uint  globalIndex = gl_LocalInvocationID.x + gl_WorkGroupSize.x * (gl_WorkGroupID.x + gl_WorkGroupID.y "
747            "* gl_NumWorkGroups.x);\n"
748         << "    ivec2 position    = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
749         << "    int   sampleNdx   = int(gl_LocalInvocationID.x);\n"
750         << "    uint  result      = 0u;\n"
751         << "\n"
752         << "    // Verify color samples\n"
753         << "    if (sampleNdx < " << static_cast<uint32_t>(numColorSamples) << ")\n"
754         << "    {\n"
755         << "        vec4 color     = texelFetch(colorImage, position, sampleNdx);\n" // for non-MS (1 sample) case, sampleNdx = 0 and will instead be LOD = 0
756         << "        vec4 diff      = abs(color - sb_cmp.data[globalIndex].color);\n"
757         << "        vec4 threshold = vec4(0.02);\n"
758         << "\n"
759         << "        if (all(lessThan(diff, threshold)))\n"
760         << "            result |= " << colorBit << ";\n"
761         << "    }\n"
762         << "    else\n"
763         << "        result |= " << colorBit << ";\n" // Pass, if sample doesn't exist
764         << "\n";
765 
766     if (isDepthFormat(depthStencilFormat))
767     {
768         src << "    // Verify depth samples\n"
769             << "    if (sampleNdx < " << static_cast<uint32_t>(numDepthStencilSamples) << ")\n"
770             << "    {\n"
771             << "        float depth     = texelFetch(depthImage, position, sampleNdx).r;\n"
772             << "        float diff      = abs(depth - sb_cmp.data[globalIndex].depth);\n"
773             << "        float threshold = 0.002;\n"
774             << "\n"
775             << "        if (diff < threshold)\n"
776             << "            result |= " << depthBit << ";\n"
777             << "    }\n"
778             << "    else\n"
779             << "        result |= " << depthBit << ";\n"
780             << "\n";
781     }
782 
783     if (isStencilFormat(depthStencilFormat))
784     {
785         src << "    // Verify stencil samples\n"
786             << "    if (sampleNdx < " << static_cast<uint32_t>(numDepthStencilSamples) << ")\n"
787             << "    {\n"
788             << "        uint stencil   = texelFetch(stencilImage, position, sampleNdx).r;\n"
789             << "        uint diff      = stencil - sb_cmp.data[globalIndex].stencil;\n"
790             << "\n"
791             << "        if (diff == 0u)\n"
792             << "            result |= " << stencilBit << ";\n"
793             << "    }\n"
794             << "    else\n"
795             << "        result |= " << stencilBit << ";\n"
796             << "\n";
797     }
798 
799     src << "    sb_out.values[globalIndex] = result;\n"
800         << "}\n";
801     programCollection.glslSources.add("comp" + nameSuffix) << glu::ComputeSource(src.str());
802 }
803 
804 //! Get a compact sample count string in format X_Y_Z
getSampleCountString(const TestParams::SampleCount & samples)805 std::string getSampleCountString(const TestParams::SampleCount &samples)
806 {
807     std::ostringstream str;
808 
809     str << static_cast<uint32_t>(samples.numCoverageSamples) << "_" << static_cast<uint32_t>(samples.numColorSamples)
810         << "_" << static_cast<uint32_t>(samples.numDepthStencilSamples);
811 
812     return str.str();
813 }
814 
initPrograms(SourceCollections & programCollection,const TestParams params)815 void initPrograms(SourceCollections &programCollection, const TestParams params)
816 {
817     // Vertex shader - position and color
818     {
819         std::ostringstream src;
820         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
821             << "\n"
822             << "layout(location = 0) in  vec4 in_position;\n"
823             << "layout(location = 1) in  vec4 in_color;\n"
824             << "layout(location = 0) out vec4 o_color;\n"
825             << "\n"
826             << "out gl_PerVertex {\n"
827             << "    vec4 gl_Position;\n"
828             << "};\n"
829             << "\n"
830             << "void main(void)\n"
831             << "{\n"
832             << "    gl_Position = in_position;\n"
833             << "    o_color     = in_color;\n"
834             << "}\n";
835 
836         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
837     }
838 
839     // Fragment shader - output color from VS
840     {
841         std::ostringstream src;
842         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
843             << "\n"
844             << "layout(location = 0) in  vec4 in_color;\n"
845             << "layout(location = 0) out vec4 o_color;\n"
846             << "\n"
847             << "void main(void)\n"
848             << "{\n"
849             << "    o_color = in_color;\n"
850             << "}\n";
851 
852         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
853     }
854 
855     // Compute shader - image verification
856     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
857     {
858         const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
859         addVerificationComputeShader(programCollection, samples.numCoverageSamples, samples.numColorSamples,
860                                      samples.numDepthStencilSamples, params.depthStencilFormat,
861                                      "_" + getSampleCountString(samples));
862     }
863 }
864 
865 //! A simple color, depth/stencil draw. Subpasses (if more than one) are independent
draw(Context & context,const TestParams & params,WorkingData & wd)866 void draw(Context &context, const TestParams &params, WorkingData &wd)
867 {
868     const InstanceInterface &vki          = context.getInstanceInterface();
869     const DeviceInterface &vk             = context.getDeviceInterface();
870     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
871     const VkDevice device                 = context.getDevice();
872     const uint32_t numSubpasses           = static_cast<uint32_t>(wd.perSubpass.size());
873 
874     RenderPassWrapper renderPass;
875     std::vector<VkSampleLocationsInfoEXT> perSubpassSampleLocationsInfo;
876     std::vector<VkAttachmentSampleLocationsEXT> attachmentSampleLocations;
877     std::vector<VkSubpassSampleLocationsEXT> subpassSampleLocations;
878 
879     if (params.useProgrammableSampleLocations)
880         for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
881         {
882             perSubpassSampleLocationsInfo.push_back(makeSampleLocationsInfo(*wd.perSubpass[subpassNdx]->pixelGrid));
883         }
884 
885     // Create a render pass and a framebuffer
886     {
887         std::vector<VkSubpassDescription> subpasses;
888         std::vector<VkImage> images;
889         std::vector<VkImageView> attachments;
890         std::vector<VkAttachmentDescription> attachmentDescriptions;
891         std::vector<VkAttachmentReference> attachmentReferences;
892 
893         // Reserve capacity to avoid invalidating pointers to elements
894         attachmentReferences.reserve(numSubpasses * 2);
895 
896         for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
897         {
898             images.push_back(wd.perSubpass[subpassNdx]->colorImage.get());
899             images.push_back(wd.perSubpass[subpassNdx]->depthStencilImage.get());
900             attachments.push_back(wd.perSubpass[subpassNdx]->colorImageView.get());
901             attachments.push_back(wd.perSubpass[subpassNdx]->depthStencilImageView.get());
902 
903             attachmentDescriptions.push_back(makeAttachmentDescription(
904                 (VkAttachmentDescriptionFlags)0,                      // VkAttachmentDescriptionFlags flags;
905                 params.colorFormat,                                   // VkFormat format;
906                 params.perSubpassSamples[subpassNdx].numColorSamples, // VkSampleCountFlagBits samples;
907                 VK_ATTACHMENT_LOAD_OP_CLEAR,                          // VkAttachmentLoadOp loadOp;
908                 VK_ATTACHMENT_STORE_OP_STORE,                         // VkAttachmentStoreOp storeOp;
909                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                      // VkAttachmentLoadOp stencilLoadOp;
910                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                     // VkAttachmentStoreOp stencilStoreOp;
911                 VK_IMAGE_LAYOUT_UNDEFINED,                            // VkImageLayout initialLayout;
912                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL              // VkImageLayout finalLayout;
913                 ));
914 
915             attachmentDescriptions.push_back(makeAttachmentDescription(
916                 (VkAttachmentDescriptionFlags)0,                             // VkAttachmentDescriptionFlags flags;
917                 params.depthStencilFormat,                                   // VkFormat format;
918                 params.perSubpassSamples[subpassNdx].numDepthStencilSamples, // VkSampleCountFlagBits samples;
919                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                 // VkAttachmentLoadOp loadOp;
920                 VK_ATTACHMENT_STORE_OP_STORE,                                // VkAttachmentStoreOp storeOp;
921                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                 // VkAttachmentLoadOp stencilLoadOp;
922                 VK_ATTACHMENT_STORE_OP_STORE,                                // VkAttachmentStoreOp stencilStoreOp;
923                 VK_IMAGE_LAYOUT_UNDEFINED,                                   // VkImageLayout initialLayout;
924                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL              // VkImageLayout finalLayout;
925                 ));
926 
927             attachmentReferences.push_back(makeAttachmentReference(static_cast<uint32_t>(attachmentReferences.size()),
928                                                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
929             const VkAttachmentReference *colorRef = &attachmentReferences.back();
930 
931             attachmentReferences.push_back(makeAttachmentReference(static_cast<uint32_t>(attachmentReferences.size()),
932                                                                    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
933             const VkAttachmentReference *depthStencilRef = &attachmentReferences.back();
934 
935             if (params.useProgrammableSampleLocations)
936             {
937                 const VkAttachmentSampleLocationsEXT newAttachmentSampleLocations = {
938                     attachmentReferences.back().attachment,    // uint32_t                    attachmentIndex;
939                     perSubpassSampleLocationsInfo[subpassNdx], // VkSampleLocationsInfoEXT    sampleLocationsInfo;
940                 };
941                 attachmentSampleLocations.push_back(newAttachmentSampleLocations);
942 
943                 const VkSubpassSampleLocationsEXT newSubpassSampleLocations = {
944                     subpassNdx,                                // uint32_t                    subpassIndex;
945                     perSubpassSampleLocationsInfo[subpassNdx], // VkSampleLocationsInfoEXT    sampleLocationsInfo;
946                 };
947                 subpassSampleLocations.push_back(newSubpassSampleLocations);
948             }
949 
950             const VkSubpassDescription subpassDescription = {
951                 (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags       flags;
952                 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint             pipelineBindPoint;
953                 0u,                              // uint32_t                        inputAttachmentCount;
954                 DE_NULL,                         // const VkAttachmentReference*    pInputAttachments;
955                 1u,                              // uint32_t                        colorAttachmentCount;
956                 colorRef,                        // const VkAttachmentReference*    pColorAttachments;
957                 DE_NULL,                         // const VkAttachmentReference*    pResolveAttachments;
958                 depthStencilRef,                 // const VkAttachmentReference*    pDepthStencilAttachment;
959                 0u,                              // uint32_t                        preserveAttachmentCount;
960                 DE_NULL,                         // const uint32_t*                 pPreserveAttachments;
961             };
962 
963             subpasses.push_back(subpassDescription);
964         }
965 
966         // Assume there are no dependencies between subpasses
967         const VkRenderPassCreateInfo renderPassInfo = {
968             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,            // VkStructureType sType;
969             DE_NULL,                                              // const void* pNext;
970             (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags flags;
971             static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
972             dataOrNullPtr(attachmentDescriptions),                // const VkAttachmentDescription* pAttachments;
973             static_cast<uint32_t>(subpasses.size()),              // uint32_t subpassCount;
974             dataOrNullPtr(subpasses),                             // const VkSubpassDescription* pSubpasses;
975             0u,                                                   // uint32_t dependencyCount;
976             DE_NULL,                                              // const VkSubpassDependency* pDependencies;
977         };
978 
979         renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
980         renderPass.createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()), dataOrNullPtr(images),
981                                      dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
982     }
983 
984     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
985     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
986     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device);
987 
988     std::vector<GraphicsPipelineWrapper> pipelines;
989 
990     for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
991     {
992         const VkSampleLocationsInfoEXT *pSampleLocationsInfo =
993             (params.useProgrammableSampleLocations ? &perSubpassSampleLocationsInfo[subpassNdx] : DE_NULL);
994 
995         pipelines.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
996                                params.pipelineConstructionType);
997         preparePipelineWrapper(pipelines.back(), pipelineLayout, *renderPass, vertexModule, fragmentModule,
998                                /*use vertex input*/ true, subpassNdx, wd.renderSize,
999                                getImageAspectFlags(params.depthStencilFormat),
1000                                params.perSubpassSamples[subpassNdx].numCoverageSamples,
1001                                /*use sample shading*/ true, params.useFragmentShadingRate, pSampleLocationsInfo);
1002     }
1003 
1004     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1005                                                           context.getUniversalQueueFamilyIndex()));
1006     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1007 
1008     beginCommandBuffer(vk, *cmdBuffer);
1009 
1010     {
1011         std::vector<VkClearValue> clearValues;
1012 
1013         for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1014         {
1015             clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1016             clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1017         }
1018 
1019         const VkRect2D renderArea = {{0u, 0u}, {wd.renderSize.x(), wd.renderSize.y()}};
1020 
1021         if (params.useProgrammableSampleLocations)
1022         {
1023             const VkRenderPassSampleLocationsBeginInfoEXT renderPassSampleLocationsBeginInfo = {
1024                 VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT, // VkStructureType                          sType;
1025                 DE_NULL, // const void*                              pNext;
1026                 static_cast<uint32_t>(
1027                     attachmentSampleLocations
1028                         .size()), // uint32_t                                 attachmentInitialSampleLocationsCount;
1029                 dataOrNullPtr(
1030                     attachmentSampleLocations), // const VkAttachmentSampleLocationsEXT*    pAttachmentInitialSampleLocations;
1031                 static_cast<uint32_t>(
1032                     subpassSampleLocations
1033                         .size()), // uint32_t                                 postSubpassSampleLocationsCount;
1034                 dataOrNullPtr(
1035                     subpassSampleLocations), // const VkSubpassSampleLocationsEXT*       pPostSubpassSampleLocations;
1036             };
1037 
1038             renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1039                              dataOrNullPtr(clearValues), VK_SUBPASS_CONTENTS_INLINE,
1040                              &renderPassSampleLocationsBeginInfo);
1041         }
1042         else
1043             renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1044                              dataOrNullPtr(clearValues));
1045     }
1046 
1047     for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1048     {
1049         if (subpassNdx != 0)
1050             renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1051 
1052         const VkDeviceSize vertexBufferOffset = 0ull;
1053         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.perSubpass[subpassNdx]->vertexBuffer.get(),
1054                                 &vertexBufferOffset);
1055 
1056         pipelines[subpassNdx].bind(*cmdBuffer);
1057 
1058         vk.cmdDraw(*cmdBuffer, wd.perSubpass[subpassNdx]->numVertices, 1u, 0u, 0u);
1059     }
1060 
1061     renderPass.end(vk, *cmdBuffer);
1062 
1063     VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1064     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1065 }
1066 
dispatchImageCheck(Context & context,const TestParams & params,WorkingData & wd,const uint32_t subpassNdx)1067 void dispatchImageCheck(Context &context, const TestParams &params, WorkingData &wd, const uint32_t subpassNdx)
1068 {
1069     const DeviceInterface &vk            = context.getDeviceInterface();
1070     const VkDevice device                = context.getDevice();
1071     WorkingData::PerSubpass &subpassData = *wd.perSubpass[subpassNdx];
1072 
1073     const Unique<VkSampler> defaultSampler(makeSampler(vk, device));
1074 
1075     // Create descriptor set
1076 
1077     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1078         DescriptorSetLayoutBuilder()
1079             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1080             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1081             .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT,
1082                                      &defaultSampler.get())
1083             .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT,
1084                                      &defaultSampler.get())
1085             .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT,
1086                                      &defaultSampler.get())
1087             .build(vk, device));
1088 
1089     const Unique<VkDescriptorPool> descriptorPool(
1090         DescriptorPoolBuilder()
1091             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
1092             .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3u)
1093             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1094 
1095     const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1096 
1097     {
1098         const VkDescriptorBufferInfo compareBufferInfo =
1099             makeDescriptorBufferInfo(*subpassData.compareBuffer, 0ull, subpassData.compareBufferSize);
1100         const VkDescriptorBufferInfo resultBufferInfo =
1101             makeDescriptorBufferInfo(*subpassData.resultBuffer, 0ull, subpassData.resultBufferSize);
1102         const VkDescriptorImageInfo colorImageInfo =
1103             makeDescriptorImageInfo(DE_NULL, *subpassData.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1104         const VkDescriptorImageInfo depthImageInfo =
1105             makeDescriptorImageInfo(DE_NULL, *subpassData.depthOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1106         const VkDescriptorImageInfo stencilImageInfo = makeDescriptorImageInfo(
1107             DE_NULL, *subpassData.stencilOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1108 
1109         DescriptorSetUpdateBuilder builder;
1110 
1111         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1112                             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
1113         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1114                             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &compareBufferInfo);
1115         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u),
1116                             VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1117 
1118         if (subpassData.depthOnlyImageView)
1119             builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u),
1120                                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo);
1121 
1122         if (subpassData.stencilOnlyImageView)
1123             builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(4u),
1124                                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &stencilImageInfo);
1125 
1126         builder.update(vk, device);
1127     }
1128 
1129     // Pipeline
1130 
1131     const std::string shaderName("comp_" + getSampleCountString(params.perSubpassSamples[subpassNdx]));
1132     const Unique<VkShaderModule> shaderModule(
1133         createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1134     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1135     const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
1136 
1137     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1138                                                           context.getUniversalQueueFamilyIndex()));
1139     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1140 
1141     beginCommandBuffer(vk, *cmdBuffer);
1142 
1143     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1144     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(),
1145                              0u, DE_NULL);
1146 
1147     vk.cmdDispatch(*cmdBuffer, wd.renderSize.x(), wd.renderSize.y(), 1u);
1148 
1149     {
1150         const VkBufferMemoryBarrier barrier = {
1151             VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
1152             DE_NULL,                                 // const void*        pNext;
1153             VK_ACCESS_SHADER_WRITE_BIT,              // VkAccessFlags      srcAccessMask;
1154             VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
1155             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
1156             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
1157             *subpassData.resultBuffer,               // VkBuffer           buffer;
1158             0ull,                                    // VkDeviceSize       offset;
1159             VK_WHOLE_SIZE,                           // VkDeviceSize       size;
1160         };
1161 
1162         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1163                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1u, &barrier, 0u,
1164                               (const VkImageMemoryBarrier *)DE_NULL);
1165     }
1166 
1167     VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1168     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1169 
1170     invalidateMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1171                                 subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1172 }
1173 
createPerSubpassData(Context & context,const TestParams & params,WorkingData & wd,const uint32_t subpassNdx)1174 void createPerSubpassData(Context &context, const TestParams &params, WorkingData &wd, const uint32_t subpassNdx)
1175 {
1176     const DeviceInterface &vk              = context.getDeviceInterface();
1177     const VkDevice device                  = context.getDevice();
1178     MovePtr<Allocator> allocator           = MovePtr<Allocator>(new SimpleAllocator(
1179         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1180     const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1181     WorkingData::PerSubpass &subpassData   = *wd.perSubpass[subpassNdx];
1182 
1183     // Create images
1184     {
1185 
1186         const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1187         const VkImageUsageFlags depthStencilImageUsageFlags =
1188             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1189 
1190         checkImageRequirements(context, params.colorFormat,
1191                                VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1192                                colorImageUsageFlags, samples.numColorSamples);
1193 
1194         subpassData.colorImage =
1195             makeImage(vk, device, params.colorFormat, wd.renderSize, samples.numColorSamples, colorImageUsageFlags);
1196         subpassData.colorImageAlloc =
1197             bindImage(vk, device, *allocator, *subpassData.colorImage, MemoryRequirement::Any);
1198         subpassData.colorImageView =
1199             makeImageView(vk, device, *subpassData.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1200                           makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1201 
1202         checkImageRequirements(context, params.depthStencilFormat,
1203                                VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1204                                depthStencilImageUsageFlags, samples.numDepthStencilSamples);
1205 
1206         subpassData.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1207                                                   samples.numDepthStencilSamples, depthStencilImageUsageFlags);
1208         subpassData.depthStencilImageAlloc =
1209             bindImage(vk, device, *allocator, *subpassData.depthStencilImage, MemoryRequirement::Any);
1210         subpassData.depthStencilImageView =
1211             makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1212                           makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1213 
1214         if (isDepthFormat(params.depthStencilFormat))
1215             subpassData.depthOnlyImageView = makeImageView(
1216                 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1217                 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1218 
1219         if (isStencilFormat(params.depthStencilFormat))
1220             subpassData.stencilOnlyImageView = makeImageView(
1221                 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1222                 makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1223     }
1224 
1225     // Create vertex and comparison buffers
1226     {
1227         const uint32_t seed                        = 123 + 19 * subpassNdx;
1228         const std::vector<CompareData> compareData = generateCompareData(
1229             seed, wd.renderSize, samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples);
1230 
1231         subpassData.compareBufferSize = static_cast<VkDeviceSize>(sizeof(CompareData) * compareData.size());
1232         subpassData.compareBuffer =
1233             makeBuffer(vk, device, subpassData.compareBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1234         subpassData.compareBufferAlloc =
1235             bindBuffer(vk, device, *allocator, *subpassData.compareBuffer, MemoryRequirement::HostVisible);
1236 
1237         deMemcpy(subpassData.compareBufferAlloc->getHostPtr(), dataOrNullPtr(compareData),
1238                  static_cast<std::size_t>(subpassData.compareBufferSize));
1239         flushMappedMemoryRange(vk, device, subpassData.compareBufferAlloc->getMemory(),
1240                                subpassData.compareBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1241 
1242         subpassData.numResultElements = static_cast<uint32_t>(compareData.size());
1243         subpassData.resultBufferSize  = static_cast<VkDeviceSize>(sizeof(uint32_t) * compareData.size());
1244         subpassData.resultBuffer =
1245             makeBuffer(vk, device, subpassData.resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1246         subpassData.resultBufferAlloc =
1247             bindBuffer(vk, device, *allocator, *subpassData.resultBuffer, MemoryRequirement::HostVisible);
1248 
1249         deMemset(subpassData.resultBufferAlloc->getHostPtr(), 0,
1250                  static_cast<std::size_t>(subpassData.resultBufferSize));
1251         flushMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1252                                subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1253 
1254         std::vector<PositionColor> vertices;
1255 
1256         if (params.useProgrammableSampleLocations)
1257         {
1258             subpassData.pixelGrid = MovePtr<MultisamplePixelGrid>(
1259                 new MultisamplePixelGrid(UVec2(wd.sampleLocationsProperties.maxSampleLocationGridSize.width,
1260                                                wd.sampleLocationsProperties.maxSampleLocationGridSize.height),
1261                                          samples.numCoverageSamples));
1262 
1263             const uint32_t locationsSeed = 211 + 4 * subpassNdx;
1264             fillSampleLocationsRandom(*subpassData.pixelGrid, wd.sampleLocationsProperties.sampleLocationSubPixelBits,
1265                                       locationsSeed);
1266             vertices = generateSubpixelTriangles(wd.renderSize, compareData,
1267                                                  getSampleLocations(*subpassData.pixelGrid, wd.renderSize));
1268         }
1269         else
1270         {
1271             const std::vector<Vec2> locations =
1272                 genFramebufferStandardSampleLocations(samples.numCoverageSamples, wd.renderSize);
1273             vertices = generateSubpixelTriangles(wd.renderSize, compareData, locations);
1274         }
1275 
1276         const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1277         subpassData.numVertices             = static_cast<uint32_t>(vertices.size());
1278         subpassData.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1279         subpassData.vertexBufferAlloc =
1280             bindBuffer(vk, device, *allocator, *subpassData.vertexBuffer, MemoryRequirement::HostVisible);
1281 
1282         deMemcpy(subpassData.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices),
1283                  static_cast<std::size_t>(vertexBufferSize));
1284         flushMappedMemoryRange(vk, device, subpassData.vertexBufferAlloc->getMemory(),
1285                                subpassData.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1286     }
1287 }
1288 
checkRequirements(Context & context,TestParams params)1289 void checkRequirements(Context &context, TestParams params)
1290 {
1291     context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1292 
1293     if (params.useProgrammableSampleLocations)
1294         context.requireDeviceFunctionality("VK_EXT_sample_locations");
1295 
1296     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1297     {
1298         const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1299         checkSampleRequirements(context, samples.numColorSamples, samples.numDepthStencilSamples,
1300                                 !params.useProgrammableSampleLocations);
1301     }
1302 
1303     const auto &vki           = context.getInstanceInterface();
1304     const auto physicalDevice = context.getPhysicalDevice();
1305 
1306     if (params.useFragmentShadingRate)
1307     {
1308         context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
1309 
1310         if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
1311             TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
1312 
1313         // Fetch information about supported fragment shading rates
1314         uint32_t supportedFragmentShadingRateCount = 0;
1315         vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL);
1316 
1317         std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(
1318             supportedFragmentShadingRateCount, {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,
1319                                                 DE_NULL,
1320                                                 vk::VK_SAMPLE_COUNT_1_BIT,
1321                                                 {1, 1}});
1322         vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount,
1323                                                      supportedFragmentShadingRates.data());
1324 
1325         uint32_t cumulativeNeededSamples = 0;
1326         for (const TestParams::SampleCount &samples : params.perSubpassSamples)
1327             cumulativeNeededSamples |= samples.numColorSamples;
1328 
1329         bool requiredRateFound = false;
1330         for (const auto &rate : supportedFragmentShadingRates)
1331         {
1332             if ((rate.fragmentSize.width == 2u) && (rate.fragmentSize.height == 2u) &&
1333                 (rate.sampleCounts & cumulativeNeededSamples))
1334             {
1335                 requiredRateFound = true;
1336                 break;
1337             }
1338         }
1339 
1340         if (!requiredRateFound)
1341             TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1342     }
1343 
1344     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1345                                           params.pipelineConstructionType);
1346 }
1347 
1348 //! Verify the values of all samples in all attachments.
test(Context & context,const TestParams params)1349 tcu::TestStatus test(Context &context, const TestParams params)
1350 {
1351     WorkingData wd;
1352     wd.renderSize = UVec2(2, 2); // Use a very small image, as we will verify all samples for all pixels
1353 
1354     // Query state related to programmable sample locations
1355     if (params.useProgrammableSampleLocations)
1356     {
1357         const InstanceInterface &vki          = context.getInstanceInterface();
1358         const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1359 
1360         wd.sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
1361         wd.sampleLocationsProperties.pNext = DE_NULL;
1362 
1363         VkPhysicalDeviceProperties2 properties = {
1364             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType               sType;
1365             &wd.sampleLocationsProperties,                  // void*                         pNext;
1366             VkPhysicalDeviceProperties(),                   // VkPhysicalDeviceProperties    properties;
1367         };
1368 
1369         vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
1370 
1371         for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1372         {
1373             if ((wd.sampleLocationsProperties.sampleLocationSampleCounts &
1374                  params.perSubpassSamples[subpassNdx].numCoverageSamples) == 0u)
1375                 TCU_THROW(NotSupportedError, "VkSampleLocationsPropertiesAMD: sample count not supported");
1376         }
1377     }
1378 
1379     // Create subpass data
1380     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1381     {
1382         wd.perSubpass.push_back(SharedPtr<WorkingData::PerSubpass>(new WorkingData::PerSubpass()));
1383         createPerSubpassData(context, params, wd, subpassNdx);
1384     }
1385 
1386     // Draw test geometry
1387     draw(context, params, wd);
1388 
1389     // Verify images with a compute shader
1390     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1391         dispatchImageCheck(context, params, wd, subpassNdx);
1392 
1393     // Test checksums
1394     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1395     {
1396         const uint32_t *const pSampleChecksumBase =
1397             static_cast<uint32_t *>(wd.perSubpass[subpassNdx]->resultBufferAlloc->getHostPtr());
1398         const bool hasDepth   = isDepthFormat(params.depthStencilFormat);
1399         const bool hasStencil = isStencilFormat(params.depthStencilFormat);
1400         bool allOk            = true;
1401 
1402         context.getTestContext().getLog()
1403             << tcu::TestLog::Message << "Verify images in subpass " << subpassNdx << tcu::TestLog::EndMessage;
1404 
1405         for (uint32_t globalSampleNdx = 0; globalSampleNdx < wd.perSubpass[subpassNdx]->numResultElements;
1406              ++globalSampleNdx)
1407         {
1408             const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1409             const uint32_t checksum                = pSampleChecksumBase[globalSampleNdx];
1410 
1411             if ((checksum & VK_IMAGE_ASPECT_COLOR_BIT) == 0u)
1412             {
1413                 reportSampleError(context.getTestContext().getLog(), "color", wd.renderSize, samples.numCoverageSamples,
1414                                   globalSampleNdx);
1415                 allOk = false;
1416             }
1417 
1418             if (hasDepth && ((checksum & VK_IMAGE_ASPECT_DEPTH_BIT) == 0u))
1419             {
1420                 reportSampleError(context.getTestContext().getLog(), "depth", wd.renderSize, samples.numCoverageSamples,
1421                                   globalSampleNdx);
1422                 allOk = false;
1423             }
1424 
1425             if (hasStencil && ((checksum & VK_IMAGE_ASPECT_STENCIL_BIT) == 0u))
1426             {
1427                 reportSampleError(context.getTestContext().getLog(), "stencil", wd.renderSize,
1428                                   samples.numCoverageSamples, globalSampleNdx);
1429                 allOk = false;
1430             }
1431         }
1432 
1433         if (!allOk)
1434             return tcu::TestStatus::fail("Multisampled image has incorrect samples");
1435     }
1436 
1437     return tcu::TestStatus::pass("Pass");
1438 }
1439 
1440 } // namespace VerifySamples
1441 
1442 namespace ShaderBuiltins
1443 {
1444 
1445 struct TestParams
1446 {
1447     PipelineConstructionType pipelineConstructionType; //!< The way pipeline is constructed
1448     VkSampleCountFlagBits numCoverageSamples;          //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
1449     VkSampleCountFlagBits numColorSamples;        //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1450     VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1451     VkFormat colorFormat;                         //!< Color attachment format
1452     VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format
1453 };
1454 
1455 struct WorkingData
1456 {
1457     UVec2 renderSize;     //!< Size of the framebuffer
1458     uint32_t numVertices; //!< Number of vertices defined in the vertex buffer
1459     Move<VkBuffer> vertexBuffer;
1460     MovePtr<Allocation> vertexBufferAlloc;
1461     Move<VkImage> colorImage;         //!< Color image
1462     Move<VkImageView> colorImageView; //!< Color attachment
1463     MovePtr<Allocation> colorImageAlloc;
1464     Move<VkImage> depthStencilImage;         //!< Depth stencil image
1465     Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment
1466     Move<VkImageView> depthOnlyImageView;    //!< Depth aspect for shader read
1467     Move<VkImageView> stencilOnlyImageView;  //!< Stencil aspect for shader read
1468     MovePtr<Allocation> depthStencilImageAlloc;
1469     Move<VkImage> resolveImage;         //!< Resolve image
1470     Move<VkImageView> resolveImageView; //!< Resolve attachment
1471     MovePtr<Allocation> resolveImageAlloc;
1472     Move<VkBuffer> colorBuffer; //!< Buffer used to copy resolve output
1473     MovePtr<Allocation> colorBufferAlloc;
1474     VkDeviceSize colorBufferSize;
1475 
WorkingDatavkt::pipeline::__anon7e964aba0111::ShaderBuiltins::WorkingData1476     WorkingData(void) : numVertices(), colorBufferSize(0)
1477     {
1478     }
1479 };
1480 
initPrograms(SourceCollections & programCollection,const TestParams params)1481 void initPrograms(SourceCollections &programCollection, const TestParams params)
1482 {
1483     // Vertex shader - no vertex data
1484     {
1485         std::ostringstream src;
1486         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1487             << "\n"
1488             << "out gl_PerVertex {\n"
1489             << "    vec4 gl_Position;\n"
1490             << "};\n"
1491             << "\n"
1492             << "void main(void)\n"
1493             << "{\n"
1494             // Specify an oversized triangle covering the whole viewport.
1495             << "    switch (gl_VertexIndex)\n"
1496             << "    {\n"
1497             << "        case 0:\n"
1498             << "            gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1499             << "            break;\n"
1500             << "        case 1:\n"
1501             << "            gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
1502             << "            break;\n"
1503             << "        case 2:\n"
1504             << "            gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
1505             << "            break;\n"
1506             << "    }\n"
1507             << "}\n";
1508 
1509         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1510     }
1511 
1512     // Fragment shader
1513     {
1514         std::ostringstream src;
1515         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1516             << "\n"
1517             << "layout(location = 0) out vec4 o_color;\n"
1518             << "\n"
1519             << "void main(void)\n"
1520             << "{\n"
1521             << "    vec4 col = vec4(0.0, 0.0, 0.0, 1.0);\n"
1522             << "\n";
1523 
1524         if (params.numColorSamples == VK_SAMPLE_COUNT_1_BIT)
1525         {
1526             const uint32_t expectedMask = ((1u << static_cast<uint32_t>(params.numCoverageSamples)) - 1u);
1527 
1528             // Expect all covered samples to be lit, the rest is zero
1529             src << "    if (gl_SampleMaskIn[0] == " << expectedMask << ")\n"
1530                 << "        col.g = 1.0;\n"
1531                 << "    else\n"
1532                 << "        col.r = 1.0;\n";
1533         }
1534         else
1535         {
1536             // Expect only a matching sample to be lit
1537             src << "    if (gl_SampleMaskIn[0] == (1 << gl_SampleID))\n"
1538                 << "        col.g = 1.0;\n"
1539                 << "    else\n"
1540                 << "        col.r = 1.0;\n"
1541                 << "\n"
1542                 << "    if (gl_SampleID >= " << static_cast<uint32_t>(params.numColorSamples)
1543                 << ")  // number of color samples, should not happen\n"
1544                 << "        col.b = 1.0;\n";
1545         }
1546 
1547         src << "\n"
1548             << "    o_color = col;\n"
1549             << "}\n";
1550 
1551         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1552     }
1553 }
1554 
1555 //! A simple color, depth/stencil draw. Single subpass, no vertex input
drawResolve(Context & context,const TestParams & params,WorkingData & wd)1556 void drawResolve(Context &context, const TestParams &params, WorkingData &wd)
1557 {
1558     const InstanceInterface &vki          = context.getInstanceInterface();
1559     const DeviceInterface &vk             = context.getDeviceInterface();
1560     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1561     const VkDevice device                 = context.getDevice();
1562     const bool needResolve                = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1563 
1564     RenderPassWrapper renderPass;
1565 
1566     // Create a render pass and a framebuffer
1567     {
1568         std::vector<VkImage> images;
1569         std::vector<VkImageView> attachments;
1570         std::vector<VkAttachmentDescription> attachmentDescriptions;
1571 
1572         images.push_back(*wd.colorImage);
1573         images.push_back(*wd.depthStencilImage);
1574         attachments.push_back(*wd.colorImageView);
1575         attachments.push_back(*wd.depthStencilImageView);
1576 
1577         attachmentDescriptions.push_back(
1578             makeAttachmentDescription((VkAttachmentDescriptionFlags)0,     // VkAttachmentDescriptionFlags flags;
1579                                       params.colorFormat,                  // VkFormat format;
1580                                       params.numColorSamples,              // VkSampleCountFlagBits samples;
1581                                       VK_ATTACHMENT_LOAD_OP_CLEAR,         // VkAttachmentLoadOp loadOp;
1582                                       VK_ATTACHMENT_STORE_OP_STORE,        // VkAttachmentStoreOp storeOp;
1583                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // VkAttachmentLoadOp stencilLoadOp;
1584                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,    // VkAttachmentStoreOp stencilStoreOp;
1585                                       VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1586                                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1587                                       ));
1588 
1589         attachmentDescriptions.push_back(
1590             makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1591                                       params.depthStencilFormat,       // VkFormat format;
1592                                       params.numDepthStencilSamples,   // VkSampleCountFlagBits samples;
1593                                       VK_ATTACHMENT_LOAD_OP_CLEAR,     // VkAttachmentLoadOp loadOp;
1594                                       VK_ATTACHMENT_STORE_OP_STORE,    // VkAttachmentStoreOp storeOp;
1595                                       VK_ATTACHMENT_LOAD_OP_CLEAR,     // VkAttachmentLoadOp stencilLoadOp;
1596                                       VK_ATTACHMENT_STORE_OP_STORE,    // VkAttachmentStoreOp stencilStoreOp;
1597                                       VK_IMAGE_LAYOUT_UNDEFINED,       // VkImageLayout initialLayout;
1598                                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
1599                                       ));
1600 
1601         if (needResolve)
1602         {
1603             images.push_back(*wd.resolveImage);
1604             attachments.push_back(*wd.resolveImageView);
1605 
1606             attachmentDescriptions.push_back(
1607                 makeAttachmentDescription((VkAttachmentDescriptionFlags)0,     // VkAttachmentDescriptionFlags flags;
1608                                           params.colorFormat,                  // VkFormat format;
1609                                           VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
1610                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // VkAttachmentLoadOp loadOp;
1611                                           VK_ATTACHMENT_STORE_OP_STORE,        // VkAttachmentStoreOp storeOp;
1612                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // VkAttachmentLoadOp stencilLoadOp;
1613                                           VK_ATTACHMENT_STORE_OP_DONT_CARE,    // VkAttachmentStoreOp stencilStoreOp;
1614                                           VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1615                                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1616                                           ));
1617         }
1618 
1619         const VkAttachmentReference colorRef = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1620         const VkAttachmentReference depthStencilRef =
1621             makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1622         const VkAttachmentReference resolveRef = makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1623 
1624         const VkSubpassDescription subpassDescription = {
1625             (VkSubpassDescriptionFlags)0,          // VkSubpassDescriptionFlags       flags;
1626             VK_PIPELINE_BIND_POINT_GRAPHICS,       // VkPipelineBindPoint             pipelineBindPoint;
1627             0u,                                    // uint32_t                        inputAttachmentCount;
1628             DE_NULL,                               // const VkAttachmentReference*    pInputAttachments;
1629             1u,                                    // uint32_t                        colorAttachmentCount;
1630             &colorRef,                             // const VkAttachmentReference*    pColorAttachments;
1631             (needResolve ? &resolveRef : DE_NULL), // const VkAttachmentReference*    pResolveAttachments;
1632             &depthStencilRef,                      // const VkAttachmentReference*    pDepthStencilAttachment;
1633             0u,                                    // uint32_t                        preserveAttachmentCount;
1634             DE_NULL,                               // const uint32_t*                 pPreserveAttachments;
1635         };
1636 
1637         // Assume there are no dependencies between subpasses
1638         VkRenderPassCreateInfo renderPassInfo = {
1639             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,            // VkStructureType sType;
1640             DE_NULL,                                              // const void* pNext;
1641             (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags flags;
1642             static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
1643             dataOrNullPtr(attachmentDescriptions),                // const VkAttachmentDescription* pAttachments;
1644             1u,                                                   // uint32_t subpassCount;
1645             &subpassDescription,                                  // const VkSubpassDescription* pSubpasses;
1646             0u,                                                   // uint32_t dependencyCount;
1647             DE_NULL,                                              // const VkSubpassDependency* pDependencies;
1648         };
1649 
1650         renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
1651         renderPass.createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()), dataOrNullPtr(images),
1652                                      dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
1653     }
1654 
1655     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1656     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1657     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device);
1658     const bool useVertexInput = false;
1659     const bool sampleShading  = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1660     const uint32_t subpassNdx = 0u;
1661     GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1662                                      params.pipelineConstructionType);
1663     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1664                                                           context.getUniversalQueueFamilyIndex()));
1665     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1666 
1667     preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, useVertexInput,
1668                            subpassNdx, wd.renderSize, getImageAspectFlags(params.depthStencilFormat),
1669                            params.numCoverageSamples, sampleShading, false);
1670 
1671     beginCommandBuffer(vk, *cmdBuffer);
1672 
1673     {
1674         std::vector<VkClearValue> clearValues;
1675         clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1676         clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1677 
1678         const VkRect2D renderArea = {{0u, 0u}, {wd.renderSize.x(), wd.renderSize.y()}};
1679 
1680         renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1681                          dataOrNullPtr(clearValues));
1682     }
1683 
1684     pipeline.bind(*cmdBuffer);
1685     vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
1686 
1687     renderPass.end(vk, *cmdBuffer);
1688 
1689     if (needResolve)
1690         recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.resolveImage, *wd.colorBuffer);
1691     else
1692         recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.colorImage, *wd.colorBuffer);
1693 
1694     VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1695     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1696 }
1697 
checkRequirements(Context & context,TestParams params)1698 void checkRequirements(Context &context, TestParams params)
1699 {
1700     context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1701 
1702     checkSampleRequirements(context, params.numColorSamples, params.numDepthStencilSamples,
1703                             false /* require standard sample locations */);
1704     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1705                                           params.pipelineConstructionType);
1706 
1707     if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1708         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1709 }
1710 
1711 //! Verify the values of shader builtins
test(Context & context,const TestParams params)1712 tcu::TestStatus test(Context &context, const TestParams params)
1713 {
1714     WorkingData wd;
1715     const DeviceInterface &vk    = context.getDeviceInterface();
1716     const VkDevice device        = context.getDevice();
1717     MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1718         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1719 
1720     wd.renderSize = UVec2(16, 16);
1721 
1722     // Create images and a color buffer
1723     {
1724 
1725         const VkImageUsageFlags colorImageUsageFlags =
1726             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1727         const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1728 
1729         checkImageRequirements(context, params.colorFormat, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
1730                                colorImageUsageFlags, params.numColorSamples);
1731 
1732         wd.colorImage =
1733             makeImage(vk, device, params.colorFormat, wd.renderSize, params.numColorSamples, colorImageUsageFlags);
1734         wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1735         wd.colorImageView  = makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1736                                            makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1737 
1738         if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1739         {
1740             wd.resolveImage =
1741                 makeImage(vk, device, params.colorFormat, wd.renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags);
1742             wd.resolveImageAlloc = bindImage(vk, device, *allocator, *wd.resolveImage, MemoryRequirement::Any);
1743             wd.resolveImageView = makeImageView(vk, device, *wd.resolveImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1744                                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1745         }
1746 
1747         // Resolve result
1748         wd.colorBufferSize  = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) *
1749                                                        wd.renderSize.x() * wd.renderSize.y());
1750         wd.colorBuffer      = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1751         wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1752 
1753         deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1754         flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(),
1755                                VK_WHOLE_SIZE);
1756 
1757         checkImageRequirements(context, params.depthStencilFormat, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
1758                                depthStencilImageUsageFlags, params.numDepthStencilSamples);
1759 
1760         wd.depthStencilImage      = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1761                                               params.numDepthStencilSamples, depthStencilImageUsageFlags);
1762         wd.depthStencilImageAlloc = bindImage(vk, device, *allocator, *wd.depthStencilImage, MemoryRequirement::Any);
1763         wd.depthStencilImageView =
1764             makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1765                           makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1766 
1767         if (isDepthFormat(params.depthStencilFormat))
1768             wd.depthOnlyImageView =
1769                 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1770                               makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1771 
1772         if (isStencilFormat(params.depthStencilFormat))
1773             wd.stencilOnlyImageView =
1774                 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1775                               makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1776     }
1777 
1778     // Draw, resolve, and copy to color buffer (see the fragment shader for details)
1779     drawResolve(context, params, wd);
1780 
1781     // Verify resolved image
1782     {
1783         const tcu::ConstPixelBufferAccess image(tcu::ConstPixelBufferAccess(
1784             mapVkFormat(params.colorFormat), tcu::IVec3(wd.renderSize.x(), wd.renderSize.y(), 1),
1785             wd.colorBufferAlloc->getHostPtr()));
1786 
1787         if (compareGreenImage(context.getTestContext().getLog(), "resolve0", "Resolved test image", image))
1788             return tcu::TestStatus::pass("Pass");
1789         else
1790             return tcu::TestStatus::fail("Some samples were incorrect");
1791     }
1792 }
1793 
1794 } // namespace ShaderBuiltins
1795 
getSampleCountGroupName(const VkSampleCountFlagBits coverageCount,const VkSampleCountFlagBits colorCount,const VkSampleCountFlagBits depthStencilCount)1796 std::string getSampleCountGroupName(const VkSampleCountFlagBits coverageCount, const VkSampleCountFlagBits colorCount,
1797                                     const VkSampleCountFlagBits depthStencilCount)
1798 {
1799     std::ostringstream str;
1800     str << "coverage_" << static_cast<uint32_t>(coverageCount) << "_color_" << static_cast<uint32_t>(colorCount)
1801         << "_depth_stencil_" << static_cast<uint32_t>(depthStencilCount);
1802     return str.str();
1803 }
1804 
getFormatShortString(const VkFormat format)1805 std::string getFormatShortString(const VkFormat format)
1806 {
1807     std::string s(de::toLower(getFormatName(format)));
1808     return s.substr(10);
1809 }
1810 
getFormatCaseName(const VkFormat colorFormat,const VkFormat depthStencilFormat)1811 std::string getFormatCaseName(const VkFormat colorFormat, const VkFormat depthStencilFormat)
1812 {
1813     std::ostringstream str;
1814     str << getFormatShortString(colorFormat) << "_" << getFormatShortString(depthStencilFormat);
1815     return str.str();
1816 }
1817 
createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)1818 void createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup *rootGroup,
1819                                               PipelineConstructionType pipelineConstructionType,
1820                                               bool useFragmentShadingRate)
1821 {
1822     const VkFormat colorFormatRange[] = {
1823         VK_FORMAT_R8G8B8A8_UNORM,
1824         // If you add more, make sure it is handled in the test/shader
1825     };
1826 
1827     const VkFormat depthStencilFormatRange[] = {
1828         VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,         VK_FORMAT_S8_UINT,
1829         VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_D32_SFLOAT_S8_UINT,
1830     };
1831 
1832     // Minimal set of formats to cover depth and stencil
1833     const VkFormat depthStencilReducedFormatRange[] = {
1834         VK_FORMAT_D16_UNORM,         //!< Must be supported
1835         VK_FORMAT_D24_UNORM_S8_UINT, //!< Either this, or the next one must be supported
1836         VK_FORMAT_D32_SFLOAT_S8_UINT,
1837     };
1838 
1839     struct SampleCase
1840     {
1841         VkSampleCountFlagBits colorSamples;
1842         VkSampleCountFlagBits depthStencilSamples;
1843     };
1844 
1845     // Currently supported EQAA cases
1846     static const SampleCase singlePassCases[] = {
1847         // Less color than depth/stencil
1848         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},  {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1849         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},  {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_16_BIT},
1850         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},  {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1851         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1852         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT},
1853     };
1854 
1855     // Multi-subpass cases
1856 
1857     static const SampleCase caseSubpassIncreaseColor_1[] = {
1858         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1859         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1860     };
1861     static const SampleCase caseSubpassIncreaseColor_2[] = {
1862         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1863         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1864         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1865     };
1866     static const SampleCase caseSubpassDecreaseColor_1[] = {
1867         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1868         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1869     };
1870     static const SampleCase caseSubpassDecreaseColor_2[] = {
1871         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1872         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1873         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1874     };
1875     static const SampleCase caseSubpassIncreaseCoverage_1[] = {
1876         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1877         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1878     };
1879     static const SampleCase caseSubpassIncreaseCoverage_2[] = {
1880         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1881         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1882         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1883     };
1884     static const SampleCase caseSubpassDecreaseCoverage_1[] = {
1885         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1886         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1887     };
1888     static const SampleCase caseSubpassDecreaseCoverage_2[] = {
1889         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1890         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1891         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1892     };
1893 
1894     static const struct
1895     {
1896         const char *const caseName;
1897         const uint32_t numSampleCases;
1898         const SampleCase *pSampleCase;
1899     } subpassCases[] = {
1900         {"multi_subpass_decrease_color_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_1), caseSubpassDecreaseColor_1},
1901         {"multi_subpass_decrease_color_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_2), caseSubpassDecreaseColor_2},
1902         {"multi_subpass_decrease_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_1),
1903          caseSubpassDecreaseCoverage_1},
1904         {"multi_subpass_decrease_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_2),
1905          caseSubpassDecreaseCoverage_2},
1906         {"multi_subpass_increase_color_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_1), caseSubpassIncreaseColor_1},
1907         {"multi_subpass_increase_color_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_2), caseSubpassIncreaseColor_2},
1908         {"multi_subpass_increase_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_1),
1909          caseSubpassIncreaseCoverage_1},
1910         {"multi_subpass_increase_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_2),
1911          caseSubpassIncreaseCoverage_2},
1912     };
1913 
1914     // Test 1: Per-sample expected value check
1915     {
1916         MovePtr<tcu::TestCaseGroup> standardLocationsGroup(
1917             new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_standard_locations"));
1918         MovePtr<tcu::TestCaseGroup> programmableLocationsGroup(
1919             new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_programmable_locations"));
1920 
1921         tcu::TestCaseGroup *locationsGroups[2] = {standardLocationsGroup.get(), programmableLocationsGroup.get()};
1922 
1923         for (uint32_t groupNdx = 0u; groupNdx < DE_LENGTH_OF_ARRAY(locationsGroups); ++groupNdx)
1924         {
1925             // Single subpass cases
1926             for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
1927             {
1928                 VerifySamples::TestParams::SampleCount samples;
1929                 samples.numColorSamples        = singlePassCases[caseNdx].colorSamples;
1930                 samples.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples;
1931                 samples.numCoverageSamples     = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1932 
1933                 VerifySamples::TestParams params;
1934                 params.pipelineConstructionType = pipelineConstructionType;
1935                 params.perSubpassSamples.push_back(samples);
1936                 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1937                 params.useFragmentShadingRate         = useFragmentShadingRate;
1938 
1939                 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1940                     new tcu::TestCaseGroup(rootGroup->getTestContext(),
1941                                            getSampleCountGroupName(samples.numCoverageSamples, samples.numColorSamples,
1942                                                                    samples.numDepthStencilSamples)
1943                                                .c_str()));
1944 
1945                 for (const VkFormat *pDepthStencilFormat = depthStencilFormatRange;
1946                      pDepthStencilFormat != DE_ARRAY_END(depthStencilFormatRange); ++pDepthStencilFormat)
1947                     for (const VkFormat *pColorFormat = colorFormatRange;
1948                          pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1949                     {
1950                         params.colorFormat        = *pColorFormat;
1951                         params.depthStencilFormat = *pDepthStencilFormat;
1952 
1953                         addFunctionCaseWithPrograms(
1954                             sampleCaseGroup.get(),
1955                             getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1956                             VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1957                     }
1958 
1959                 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1960             }
1961 
1962             // Multi subpass cases
1963             for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(subpassCases); ++caseNdx)
1964             {
1965                 VerifySamples::TestParams params;
1966                 params.pipelineConstructionType       = pipelineConstructionType;
1967                 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1968                 params.useFragmentShadingRate         = useFragmentShadingRate;
1969 
1970                 for (uint32_t subpassNdx = 0; subpassNdx < subpassCases[caseNdx].numSampleCases; ++subpassNdx)
1971                 {
1972                     VerifySamples::TestParams::SampleCount samples;
1973                     samples.numColorSamples        = subpassCases[caseNdx].pSampleCase[subpassNdx].colorSamples;
1974                     samples.numDepthStencilSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].depthStencilSamples;
1975                     samples.numCoverageSamples     = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1976                     params.perSubpassSamples.push_back(samples);
1977                 }
1978 
1979                 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1980                     new tcu::TestCaseGroup(rootGroup->getTestContext(), subpassCases[caseNdx].caseName));
1981 
1982                 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
1983                      pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
1984                     for (const VkFormat *pColorFormat = colorFormatRange;
1985                          pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1986                     {
1987                         params.colorFormat        = *pColorFormat;
1988                         params.depthStencilFormat = *pDepthStencilFormat;
1989 
1990                         addFunctionCaseWithPrograms(
1991                             sampleCaseGroup.get(),
1992                             getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1993                             VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1994                     }
1995 
1996                 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1997             }
1998         }
1999 
2000         rootGroup->addChild(standardLocationsGroup.release());
2001         rootGroup->addChild(programmableLocationsGroup.release());
2002     }
2003 
2004     // Test 2: Shader built-ins check
2005     if (!useFragmentShadingRate)
2006     {
2007         MovePtr<tcu::TestCaseGroup> builtinsGroup(
2008             new tcu::TestCaseGroup(rootGroup->getTestContext(), "shader_builtins"));
2009 
2010         for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
2011         {
2012             ShaderBuiltins::TestParams params;
2013             params.pipelineConstructionType = pipelineConstructionType;
2014             params.numColorSamples          = singlePassCases[caseNdx].colorSamples;
2015             params.numDepthStencilSamples   = singlePassCases[caseNdx].depthStencilSamples;
2016             params.numCoverageSamples       = de::max(params.numColorSamples, params.numDepthStencilSamples);
2017 
2018             MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(
2019                 rootGroup->getTestContext(), getSampleCountGroupName(params.numCoverageSamples, params.numColorSamples,
2020                                                                      params.numDepthStencilSamples)
2021                                                  .c_str()));
2022 
2023             for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
2024                  pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
2025                 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange);
2026                      ++pColorFormat)
2027                 {
2028                     params.colorFormat        = *pColorFormat;
2029                     params.depthStencilFormat = *pDepthStencilFormat;
2030 
2031                     addFunctionCaseWithPrograms(
2032                         sampleCaseGroup.get(), getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
2033                         ShaderBuiltins::checkRequirements, ShaderBuiltins::initPrograms, ShaderBuiltins::test, params);
2034                 }
2035 
2036             builtinsGroup->addChild(sampleCaseGroup.release());
2037         }
2038 
2039         rootGroup->addChild(builtinsGroup.release());
2040     }
2041 }
2042 
2043 } // namespace
2044 
createMultisampleMixedAttachmentSamplesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)2045 tcu::TestCaseGroup *createMultisampleMixedAttachmentSamplesTests(tcu::TestContext &testCtx,
2046                                                                  PipelineConstructionType pipelineConstructionType,
2047                                                                  bool useFragmentShadingRate)
2048 {
2049     // Test a graphics pipeline with varying sample count per color and depth/stencil attachments
2050     return createTestGroup(testCtx, "mixed_attachment_samples", createMixedAttachmentSamplesTestsInGroup,
2051                            pipelineConstructionType, useFragmentShadingRate);
2052 }
2053 
2054 } // namespace pipeline
2055 } // namespace vkt
2056