• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anonea1bc53a0111::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         nullptr,                                 // 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         nullptr,                             // 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         nullptr,                             // 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=nullptr)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 = nullptr)
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         nullptr,                                                      // 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         nullptr,                                                           // 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         nullptr,                                                  // const void* pNext;
222         (VkPipelineMultisampleStateCreateFlags)0,                 // VkPipelineMultisampleStateCreateFlags flags;
223         numSamples,                                               // VkSampleCountFlagBits rasterizationSamples;
224         sampleShadingEnable,                                      // VkBool32 sampleShadingEnable;
225         1.0f,                                                     // float minSampleShading;
226         nullptr,                                                  // 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         nullptr,                                                    // 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         nullptr,                                                  // 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         nullptr,                                                                // 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(), nullptr,
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 = nullptr;
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::__anonea1bc53a0111::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             nullptr,                                // 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, nullptr, 0u, nullptr, 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             nullptr,                                 // 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, nullptr, 1u, &barrier, 0u, nullptr);
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::__anonea1bc53a0111::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::__anonea1bc53a0111::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::__anonea1bc53a0111::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                 nullptr,                         // const VkAttachmentReference*    pInputAttachments;
955                 1u,                              // uint32_t                        colorAttachmentCount;
956                 colorRef,                        // const VkAttachmentReference*    pColorAttachments;
957                 nullptr,                         // const VkAttachmentReference*    pResolveAttachments;
958                 depthStencilRef,                 // const VkAttachmentReference*    pDepthStencilAttachment;
959                 0u,                              // uint32_t                        preserveAttachmentCount;
960                 nullptr,                         // 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             nullptr,                                              // 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             nullptr,                                              // 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] : nullptr);
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                 nullptr, // 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 = makeDescriptorImageInfo(
1103             VK_NULL_HANDLE, *subpassData.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1104         const VkDescriptorImageInfo depthImageInfo = makeDescriptorImageInfo(
1105             VK_NULL_HANDLE, *subpassData.depthOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1106         const VkDescriptorImageInfo stencilImageInfo = makeDescriptorImageInfo(
1107             VK_NULL_HANDLE, *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, nullptr);
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             nullptr,                                 // 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, nullptr, 1u, &barrier, 0u, nullptr);
1164     }
1165 
1166     VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1167     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1168 
1169     invalidateMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1170                                 subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1171 }
1172 
createPerSubpassData(Context & context,const TestParams & params,WorkingData & wd,const uint32_t subpassNdx)1173 void createPerSubpassData(Context &context, const TestParams &params, WorkingData &wd, const uint32_t subpassNdx)
1174 {
1175     const DeviceInterface &vk              = context.getDeviceInterface();
1176     const VkDevice device                  = context.getDevice();
1177     MovePtr<Allocator> allocator           = MovePtr<Allocator>(new SimpleAllocator(
1178         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1179     const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1180     WorkingData::PerSubpass &subpassData   = *wd.perSubpass[subpassNdx];
1181 
1182     // Create images
1183     {
1184 
1185         const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1186         const VkImageUsageFlags depthStencilImageUsageFlags =
1187             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1188 
1189         checkImageRequirements(context, params.colorFormat,
1190                                VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1191                                colorImageUsageFlags, samples.numColorSamples);
1192 
1193         subpassData.colorImage =
1194             makeImage(vk, device, params.colorFormat, wd.renderSize, samples.numColorSamples, colorImageUsageFlags);
1195         subpassData.colorImageAlloc =
1196             bindImage(vk, device, *allocator, *subpassData.colorImage, MemoryRequirement::Any);
1197         subpassData.colorImageView =
1198             makeImageView(vk, device, *subpassData.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1199                           makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1200 
1201         checkImageRequirements(context, params.depthStencilFormat,
1202                                VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1203                                depthStencilImageUsageFlags, samples.numDepthStencilSamples);
1204 
1205         subpassData.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1206                                                   samples.numDepthStencilSamples, depthStencilImageUsageFlags);
1207         subpassData.depthStencilImageAlloc =
1208             bindImage(vk, device, *allocator, *subpassData.depthStencilImage, MemoryRequirement::Any);
1209         subpassData.depthStencilImageView =
1210             makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1211                           makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1212 
1213         if (isDepthFormat(params.depthStencilFormat))
1214             subpassData.depthOnlyImageView = makeImageView(
1215                 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1216                 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1217 
1218         if (isStencilFormat(params.depthStencilFormat))
1219             subpassData.stencilOnlyImageView = makeImageView(
1220                 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1221                 makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1222     }
1223 
1224     // Create vertex and comparison buffers
1225     {
1226         const uint32_t seed                        = 123 + 19 * subpassNdx;
1227         const std::vector<CompareData> compareData = generateCompareData(
1228             seed, wd.renderSize, samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples);
1229 
1230         subpassData.compareBufferSize = static_cast<VkDeviceSize>(sizeof(CompareData) * compareData.size());
1231         subpassData.compareBuffer =
1232             makeBuffer(vk, device, subpassData.compareBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1233         subpassData.compareBufferAlloc =
1234             bindBuffer(vk, device, *allocator, *subpassData.compareBuffer, MemoryRequirement::HostVisible);
1235 
1236         deMemcpy(subpassData.compareBufferAlloc->getHostPtr(), dataOrNullPtr(compareData),
1237                  static_cast<std::size_t>(subpassData.compareBufferSize));
1238         flushMappedMemoryRange(vk, device, subpassData.compareBufferAlloc->getMemory(),
1239                                subpassData.compareBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1240 
1241         subpassData.numResultElements = static_cast<uint32_t>(compareData.size());
1242         subpassData.resultBufferSize  = static_cast<VkDeviceSize>(sizeof(uint32_t) * compareData.size());
1243         subpassData.resultBuffer =
1244             makeBuffer(vk, device, subpassData.resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1245         subpassData.resultBufferAlloc =
1246             bindBuffer(vk, device, *allocator, *subpassData.resultBuffer, MemoryRequirement::HostVisible);
1247 
1248         deMemset(subpassData.resultBufferAlloc->getHostPtr(), 0,
1249                  static_cast<std::size_t>(subpassData.resultBufferSize));
1250         flushMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1251                                subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1252 
1253         std::vector<PositionColor> vertices;
1254 
1255         if (params.useProgrammableSampleLocations)
1256         {
1257             subpassData.pixelGrid = MovePtr<MultisamplePixelGrid>(
1258                 new MultisamplePixelGrid(UVec2(wd.sampleLocationsProperties.maxSampleLocationGridSize.width,
1259                                                wd.sampleLocationsProperties.maxSampleLocationGridSize.height),
1260                                          samples.numCoverageSamples));
1261 
1262             const uint32_t locationsSeed = 211 + 4 * subpassNdx;
1263             fillSampleLocationsRandom(*subpassData.pixelGrid, wd.sampleLocationsProperties.sampleLocationSubPixelBits,
1264                                       locationsSeed);
1265             vertices = generateSubpixelTriangles(wd.renderSize, compareData,
1266                                                  getSampleLocations(*subpassData.pixelGrid, wd.renderSize));
1267         }
1268         else
1269         {
1270             const std::vector<Vec2> locations =
1271                 genFramebufferStandardSampleLocations(samples.numCoverageSamples, wd.renderSize);
1272             vertices = generateSubpixelTriangles(wd.renderSize, compareData, locations);
1273         }
1274 
1275         const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1276         subpassData.numVertices             = static_cast<uint32_t>(vertices.size());
1277         subpassData.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1278         subpassData.vertexBufferAlloc =
1279             bindBuffer(vk, device, *allocator, *subpassData.vertexBuffer, MemoryRequirement::HostVisible);
1280 
1281         deMemcpy(subpassData.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices),
1282                  static_cast<std::size_t>(vertexBufferSize));
1283         flushMappedMemoryRange(vk, device, subpassData.vertexBufferAlloc->getMemory(),
1284                                subpassData.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1285     }
1286 }
1287 
checkRequirements(Context & context,TestParams params)1288 void checkRequirements(Context &context, TestParams params)
1289 {
1290     context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1291 
1292     if (params.useProgrammableSampleLocations)
1293         context.requireDeviceFunctionality("VK_EXT_sample_locations");
1294 
1295     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1296     {
1297         const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1298         checkSampleRequirements(context, samples.numColorSamples, samples.numDepthStencilSamples,
1299                                 !params.useProgrammableSampleLocations);
1300     }
1301 
1302     const auto &vki           = context.getInstanceInterface();
1303     const auto physicalDevice = context.getPhysicalDevice();
1304 
1305     if (params.useFragmentShadingRate)
1306     {
1307         context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
1308 
1309         if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
1310             TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
1311 
1312         // Fetch information about supported fragment shading rates
1313         uint32_t supportedFragmentShadingRateCount = 0;
1314         vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, nullptr);
1315 
1316         std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(
1317             supportedFragmentShadingRateCount, {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,
1318                                                 nullptr,
1319                                                 vk::VK_SAMPLE_COUNT_1_BIT,
1320                                                 {1, 1}});
1321         vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount,
1322                                                      supportedFragmentShadingRates.data());
1323 
1324         uint32_t cumulativeNeededSamples = 0;
1325         for (const TestParams::SampleCount &samples : params.perSubpassSamples)
1326             cumulativeNeededSamples |= samples.numColorSamples;
1327 
1328         bool requiredRateFound = false;
1329         for (const auto &rate : supportedFragmentShadingRates)
1330         {
1331             if ((rate.fragmentSize.width == 2u) && (rate.fragmentSize.height == 2u) &&
1332                 (rate.sampleCounts & cumulativeNeededSamples))
1333             {
1334                 requiredRateFound = true;
1335                 break;
1336             }
1337         }
1338 
1339         if (!requiredRateFound)
1340             TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1341     }
1342 
1343     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1344                                           params.pipelineConstructionType);
1345 }
1346 
1347 //! Verify the values of all samples in all attachments.
test(Context & context,const TestParams params)1348 tcu::TestStatus test(Context &context, const TestParams params)
1349 {
1350     WorkingData wd;
1351     wd.renderSize = UVec2(2, 2); // Use a very small image, as we will verify all samples for all pixels
1352 
1353     // Query state related to programmable sample locations
1354     if (params.useProgrammableSampleLocations)
1355     {
1356         const InstanceInterface &vki          = context.getInstanceInterface();
1357         const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1358 
1359         wd.sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
1360         wd.sampleLocationsProperties.pNext = nullptr;
1361 
1362         VkPhysicalDeviceProperties2 properties = {
1363             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType               sType;
1364             &wd.sampleLocationsProperties,                  // void*                         pNext;
1365             VkPhysicalDeviceProperties(),                   // VkPhysicalDeviceProperties    properties;
1366         };
1367 
1368         vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
1369 
1370         for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1371         {
1372             if ((wd.sampleLocationsProperties.sampleLocationSampleCounts &
1373                  params.perSubpassSamples[subpassNdx].numCoverageSamples) == 0u)
1374                 TCU_THROW(NotSupportedError, "VkSampleLocationsPropertiesAMD: sample count not supported");
1375         }
1376     }
1377 
1378     // Create subpass data
1379     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1380     {
1381         wd.perSubpass.push_back(SharedPtr<WorkingData::PerSubpass>(new WorkingData::PerSubpass()));
1382         createPerSubpassData(context, params, wd, subpassNdx);
1383     }
1384 
1385     // Draw test geometry
1386     draw(context, params, wd);
1387 
1388     // Verify images with a compute shader
1389     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1390         dispatchImageCheck(context, params, wd, subpassNdx);
1391 
1392     // Test checksums
1393     for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1394     {
1395         const uint32_t *const pSampleChecksumBase =
1396             static_cast<uint32_t *>(wd.perSubpass[subpassNdx]->resultBufferAlloc->getHostPtr());
1397         const bool hasDepth   = isDepthFormat(params.depthStencilFormat);
1398         const bool hasStencil = isStencilFormat(params.depthStencilFormat);
1399         bool allOk            = true;
1400 
1401         context.getTestContext().getLog()
1402             << tcu::TestLog::Message << "Verify images in subpass " << subpassNdx << tcu::TestLog::EndMessage;
1403 
1404         for (uint32_t globalSampleNdx = 0; globalSampleNdx < wd.perSubpass[subpassNdx]->numResultElements;
1405              ++globalSampleNdx)
1406         {
1407             const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1408             const uint32_t checksum                = pSampleChecksumBase[globalSampleNdx];
1409 
1410             if ((checksum & VK_IMAGE_ASPECT_COLOR_BIT) == 0u)
1411             {
1412                 reportSampleError(context.getTestContext().getLog(), "color", wd.renderSize, samples.numCoverageSamples,
1413                                   globalSampleNdx);
1414                 allOk = false;
1415             }
1416 
1417             if (hasDepth && ((checksum & VK_IMAGE_ASPECT_DEPTH_BIT) == 0u))
1418             {
1419                 reportSampleError(context.getTestContext().getLog(), "depth", wd.renderSize, samples.numCoverageSamples,
1420                                   globalSampleNdx);
1421                 allOk = false;
1422             }
1423 
1424             if (hasStencil && ((checksum & VK_IMAGE_ASPECT_STENCIL_BIT) == 0u))
1425             {
1426                 reportSampleError(context.getTestContext().getLog(), "stencil", wd.renderSize,
1427                                   samples.numCoverageSamples, globalSampleNdx);
1428                 allOk = false;
1429             }
1430         }
1431 
1432         if (!allOk)
1433             return tcu::TestStatus::fail("Multisampled image has incorrect samples");
1434     }
1435 
1436     return tcu::TestStatus::pass("Pass");
1437 }
1438 
1439 } // namespace VerifySamples
1440 
1441 namespace ShaderBuiltins
1442 {
1443 
1444 struct TestParams
1445 {
1446     PipelineConstructionType pipelineConstructionType; //!< The way pipeline is constructed
1447     VkSampleCountFlagBits numCoverageSamples;          //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
1448     VkSampleCountFlagBits numColorSamples;        //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1449     VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1450     VkFormat colorFormat;                         //!< Color attachment format
1451     VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format
1452 };
1453 
1454 struct WorkingData
1455 {
1456     UVec2 renderSize;     //!< Size of the framebuffer
1457     uint32_t numVertices; //!< Number of vertices defined in the vertex buffer
1458     Move<VkBuffer> vertexBuffer;
1459     MovePtr<Allocation> vertexBufferAlloc;
1460     Move<VkImage> colorImage;         //!< Color image
1461     Move<VkImageView> colorImageView; //!< Color attachment
1462     MovePtr<Allocation> colorImageAlloc;
1463     Move<VkImage> depthStencilImage;         //!< Depth stencil image
1464     Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment
1465     Move<VkImageView> depthOnlyImageView;    //!< Depth aspect for shader read
1466     Move<VkImageView> stencilOnlyImageView;  //!< Stencil aspect for shader read
1467     MovePtr<Allocation> depthStencilImageAlloc;
1468     Move<VkImage> resolveImage;         //!< Resolve image
1469     Move<VkImageView> resolveImageView; //!< Resolve attachment
1470     MovePtr<Allocation> resolveImageAlloc;
1471     Move<VkBuffer> colorBuffer; //!< Buffer used to copy resolve output
1472     MovePtr<Allocation> colorBufferAlloc;
1473     VkDeviceSize colorBufferSize;
1474 
WorkingDatavkt::pipeline::__anonea1bc53a0111::ShaderBuiltins::WorkingData1475     WorkingData(void) : numVertices(), colorBufferSize(0)
1476     {
1477     }
1478 };
1479 
initPrograms(SourceCollections & programCollection,const TestParams params)1480 void initPrograms(SourceCollections &programCollection, const TestParams params)
1481 {
1482     // Vertex shader - no vertex data
1483     {
1484         std::ostringstream src;
1485         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1486             << "\n"
1487             << "out gl_PerVertex {\n"
1488             << "    vec4 gl_Position;\n"
1489             << "};\n"
1490             << "\n"
1491             << "void main(void)\n"
1492             << "{\n"
1493             // Specify an oversized triangle covering the whole viewport.
1494             << "    switch (gl_VertexIndex)\n"
1495             << "    {\n"
1496             << "        case 0:\n"
1497             << "            gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1498             << "            break;\n"
1499             << "        case 1:\n"
1500             << "            gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
1501             << "            break;\n"
1502             << "        case 2:\n"
1503             << "            gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
1504             << "            break;\n"
1505             << "    }\n"
1506             << "}\n";
1507 
1508         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1509     }
1510 
1511     // Fragment shader
1512     {
1513         std::ostringstream src;
1514         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1515             << "\n"
1516             << "layout(location = 0) out vec4 o_color;\n"
1517             << "\n"
1518             << "void main(void)\n"
1519             << "{\n"
1520             << "    vec4 col = vec4(0.0, 0.0, 0.0, 1.0);\n"
1521             << "\n";
1522 
1523         if (params.numColorSamples == VK_SAMPLE_COUNT_1_BIT)
1524         {
1525             const uint32_t expectedMask = ((1u << static_cast<uint32_t>(params.numCoverageSamples)) - 1u);
1526 
1527             // Expect all covered samples to be lit, the rest is zero
1528             src << "    if (gl_SampleMaskIn[0] == " << expectedMask << ")\n"
1529                 << "        col.g = 1.0;\n"
1530                 << "    else\n"
1531                 << "        col.r = 1.0;\n";
1532         }
1533         else
1534         {
1535             // Expect only a matching sample to be lit
1536             src << "    if (gl_SampleMaskIn[0] == (1 << gl_SampleID))\n"
1537                 << "        col.g = 1.0;\n"
1538                 << "    else\n"
1539                 << "        col.r = 1.0;\n"
1540                 << "\n"
1541                 << "    if (gl_SampleID >= " << static_cast<uint32_t>(params.numColorSamples)
1542                 << ")  // number of color samples, should not happen\n"
1543                 << "        col.b = 1.0;\n";
1544         }
1545 
1546         src << "\n"
1547             << "    o_color = col;\n"
1548             << "}\n";
1549 
1550         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1551     }
1552 }
1553 
1554 //! A simple color, depth/stencil draw. Single subpass, no vertex input
drawResolve(Context & context,const TestParams & params,WorkingData & wd)1555 void drawResolve(Context &context, const TestParams &params, WorkingData &wd)
1556 {
1557     const InstanceInterface &vki          = context.getInstanceInterface();
1558     const DeviceInterface &vk             = context.getDeviceInterface();
1559     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1560     const VkDevice device                 = context.getDevice();
1561     const bool needResolve                = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1562 
1563     RenderPassWrapper renderPass;
1564 
1565     // Create a render pass and a framebuffer
1566     {
1567         std::vector<VkImage> images;
1568         std::vector<VkImageView> attachments;
1569         std::vector<VkAttachmentDescription> attachmentDescriptions;
1570 
1571         images.push_back(*wd.colorImage);
1572         images.push_back(*wd.depthStencilImage);
1573         attachments.push_back(*wd.colorImageView);
1574         attachments.push_back(*wd.depthStencilImageView);
1575 
1576         attachmentDescriptions.push_back(
1577             makeAttachmentDescription((VkAttachmentDescriptionFlags)0,     // VkAttachmentDescriptionFlags flags;
1578                                       params.colorFormat,                  // VkFormat format;
1579                                       params.numColorSamples,              // VkSampleCountFlagBits samples;
1580                                       VK_ATTACHMENT_LOAD_OP_CLEAR,         // VkAttachmentLoadOp loadOp;
1581                                       VK_ATTACHMENT_STORE_OP_STORE,        // VkAttachmentStoreOp storeOp;
1582                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // VkAttachmentLoadOp stencilLoadOp;
1583                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,    // VkAttachmentStoreOp stencilStoreOp;
1584                                       VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1585                                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1586                                       ));
1587 
1588         attachmentDescriptions.push_back(
1589             makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1590                                       params.depthStencilFormat,       // VkFormat format;
1591                                       params.numDepthStencilSamples,   // VkSampleCountFlagBits samples;
1592                                       VK_ATTACHMENT_LOAD_OP_CLEAR,     // VkAttachmentLoadOp loadOp;
1593                                       VK_ATTACHMENT_STORE_OP_STORE,    // VkAttachmentStoreOp storeOp;
1594                                       VK_ATTACHMENT_LOAD_OP_CLEAR,     // VkAttachmentLoadOp stencilLoadOp;
1595                                       VK_ATTACHMENT_STORE_OP_STORE,    // VkAttachmentStoreOp stencilStoreOp;
1596                                       VK_IMAGE_LAYOUT_UNDEFINED,       // VkImageLayout initialLayout;
1597                                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
1598                                       ));
1599 
1600         if (needResolve)
1601         {
1602             images.push_back(*wd.resolveImage);
1603             attachments.push_back(*wd.resolveImageView);
1604 
1605             attachmentDescriptions.push_back(
1606                 makeAttachmentDescription((VkAttachmentDescriptionFlags)0,     // VkAttachmentDescriptionFlags flags;
1607                                           params.colorFormat,                  // VkFormat format;
1608                                           VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
1609                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // VkAttachmentLoadOp loadOp;
1610                                           VK_ATTACHMENT_STORE_OP_STORE,        // VkAttachmentStoreOp storeOp;
1611                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // VkAttachmentLoadOp stencilLoadOp;
1612                                           VK_ATTACHMENT_STORE_OP_DONT_CARE,    // VkAttachmentStoreOp stencilStoreOp;
1613                                           VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1614                                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1615                                           ));
1616         }
1617 
1618         const VkAttachmentReference colorRef = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1619         const VkAttachmentReference depthStencilRef =
1620             makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1621         const VkAttachmentReference resolveRef = makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1622 
1623         const VkSubpassDescription subpassDescription = {
1624             (VkSubpassDescriptionFlags)0,          // VkSubpassDescriptionFlags       flags;
1625             VK_PIPELINE_BIND_POINT_GRAPHICS,       // VkPipelineBindPoint             pipelineBindPoint;
1626             0u,                                    // uint32_t                        inputAttachmentCount;
1627             nullptr,                               // const VkAttachmentReference*    pInputAttachments;
1628             1u,                                    // uint32_t                        colorAttachmentCount;
1629             &colorRef,                             // const VkAttachmentReference*    pColorAttachments;
1630             (needResolve ? &resolveRef : nullptr), // const VkAttachmentReference*    pResolveAttachments;
1631             &depthStencilRef,                      // const VkAttachmentReference*    pDepthStencilAttachment;
1632             0u,                                    // uint32_t                        preserveAttachmentCount;
1633             nullptr,                               // const uint32_t*                 pPreserveAttachments;
1634         };
1635 
1636         // Assume there are no dependencies between subpasses
1637         VkRenderPassCreateInfo renderPassInfo = {
1638             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,            // VkStructureType sType;
1639             nullptr,                                              // const void* pNext;
1640             (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags flags;
1641             static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
1642             dataOrNullPtr(attachmentDescriptions),                // const VkAttachmentDescription* pAttachments;
1643             1u,                                                   // uint32_t subpassCount;
1644             &subpassDescription,                                  // const VkSubpassDescription* pSubpasses;
1645             0u,                                                   // uint32_t dependencyCount;
1646             nullptr,                                              // const VkSubpassDependency* pDependencies;
1647         };
1648 
1649         renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
1650         renderPass.createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()), dataOrNullPtr(images),
1651                                      dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
1652     }
1653 
1654     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1655     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1656     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device);
1657     const bool useVertexInput = false;
1658     const bool sampleShading  = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1659     const uint32_t subpassNdx = 0u;
1660     GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1661                                      params.pipelineConstructionType);
1662     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1663                                                           context.getUniversalQueueFamilyIndex()));
1664     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1665 
1666     preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, useVertexInput,
1667                            subpassNdx, wd.renderSize, getImageAspectFlags(params.depthStencilFormat),
1668                            params.numCoverageSamples, sampleShading, false);
1669 
1670     beginCommandBuffer(vk, *cmdBuffer);
1671 
1672     {
1673         std::vector<VkClearValue> clearValues;
1674         clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1675         clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1676 
1677         const VkRect2D renderArea = {{0u, 0u}, {wd.renderSize.x(), wd.renderSize.y()}};
1678 
1679         renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1680                          dataOrNullPtr(clearValues));
1681     }
1682 
1683     pipeline.bind(*cmdBuffer);
1684     vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
1685 
1686     renderPass.end(vk, *cmdBuffer);
1687 
1688     if (needResolve)
1689         recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.resolveImage, *wd.colorBuffer);
1690     else
1691         recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.colorImage, *wd.colorBuffer);
1692 
1693     VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1694     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1695 }
1696 
checkRequirements(Context & context,TestParams params)1697 void checkRequirements(Context &context, TestParams params)
1698 {
1699     context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1700 
1701     checkSampleRequirements(context, params.numColorSamples, params.numDepthStencilSamples,
1702                             false /* require standard sample locations */);
1703     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1704                                           params.pipelineConstructionType);
1705 
1706     if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1707         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1708 }
1709 
1710 //! Verify the values of shader builtins
test(Context & context,const TestParams params)1711 tcu::TestStatus test(Context &context, const TestParams params)
1712 {
1713     WorkingData wd;
1714     const DeviceInterface &vk    = context.getDeviceInterface();
1715     const VkDevice device        = context.getDevice();
1716     MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1717         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1718 
1719     wd.renderSize = UVec2(16, 16);
1720 
1721     // Create images and a color buffer
1722     {
1723 
1724         const VkImageUsageFlags colorImageUsageFlags =
1725             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1726         const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1727 
1728         checkImageRequirements(context, params.colorFormat, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
1729                                colorImageUsageFlags, params.numColorSamples);
1730 
1731         wd.colorImage =
1732             makeImage(vk, device, params.colorFormat, wd.renderSize, params.numColorSamples, colorImageUsageFlags);
1733         wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1734         wd.colorImageView  = makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1735                                            makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1736 
1737         if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1738         {
1739             wd.resolveImage =
1740                 makeImage(vk, device, params.colorFormat, wd.renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags);
1741             wd.resolveImageAlloc = bindImage(vk, device, *allocator, *wd.resolveImage, MemoryRequirement::Any);
1742             wd.resolveImageView = makeImageView(vk, device, *wd.resolveImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1743                                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1744         }
1745 
1746         // Resolve result
1747         wd.colorBufferSize  = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) *
1748                                                        wd.renderSize.x() * wd.renderSize.y());
1749         wd.colorBuffer      = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1750         wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1751 
1752         deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1753         flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(),
1754                                VK_WHOLE_SIZE);
1755 
1756         checkImageRequirements(context, params.depthStencilFormat, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
1757                                depthStencilImageUsageFlags, params.numDepthStencilSamples);
1758 
1759         wd.depthStencilImage      = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1760                                               params.numDepthStencilSamples, depthStencilImageUsageFlags);
1761         wd.depthStencilImageAlloc = bindImage(vk, device, *allocator, *wd.depthStencilImage, MemoryRequirement::Any);
1762         wd.depthStencilImageView =
1763             makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1764                           makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1765 
1766         if (isDepthFormat(params.depthStencilFormat))
1767             wd.depthOnlyImageView =
1768                 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1769                               makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1770 
1771         if (isStencilFormat(params.depthStencilFormat))
1772             wd.stencilOnlyImageView =
1773                 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1774                               makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1775     }
1776 
1777     // Draw, resolve, and copy to color buffer (see the fragment shader for details)
1778     drawResolve(context, params, wd);
1779 
1780     // Verify resolved image
1781     {
1782         const tcu::ConstPixelBufferAccess image(tcu::ConstPixelBufferAccess(
1783             mapVkFormat(params.colorFormat), tcu::IVec3(wd.renderSize.x(), wd.renderSize.y(), 1),
1784             wd.colorBufferAlloc->getHostPtr()));
1785 
1786         if (compareGreenImage(context.getTestContext().getLog(), "resolve0", "Resolved test image", image))
1787             return tcu::TestStatus::pass("Pass");
1788         else
1789             return tcu::TestStatus::fail("Some samples were incorrect");
1790     }
1791 }
1792 
1793 } // namespace ShaderBuiltins
1794 
getSampleCountGroupName(const VkSampleCountFlagBits coverageCount,const VkSampleCountFlagBits colorCount,const VkSampleCountFlagBits depthStencilCount)1795 std::string getSampleCountGroupName(const VkSampleCountFlagBits coverageCount, const VkSampleCountFlagBits colorCount,
1796                                     const VkSampleCountFlagBits depthStencilCount)
1797 {
1798     std::ostringstream str;
1799     str << "coverage_" << static_cast<uint32_t>(coverageCount) << "_color_" << static_cast<uint32_t>(colorCount)
1800         << "_depth_stencil_" << static_cast<uint32_t>(depthStencilCount);
1801     return str.str();
1802 }
1803 
getFormatShortString(const VkFormat format)1804 std::string getFormatShortString(const VkFormat format)
1805 {
1806     std::string s(de::toLower(getFormatName(format)));
1807     return s.substr(10);
1808 }
1809 
getFormatCaseName(const VkFormat colorFormat,const VkFormat depthStencilFormat)1810 std::string getFormatCaseName(const VkFormat colorFormat, const VkFormat depthStencilFormat)
1811 {
1812     std::ostringstream str;
1813     str << getFormatShortString(colorFormat) << "_" << getFormatShortString(depthStencilFormat);
1814     return str.str();
1815 }
1816 
createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)1817 void createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup *rootGroup,
1818                                               PipelineConstructionType pipelineConstructionType,
1819                                               bool useFragmentShadingRate)
1820 {
1821     const VkFormat colorFormatRange[] = {
1822         VK_FORMAT_R8G8B8A8_UNORM,
1823         // If you add more, make sure it is handled in the test/shader
1824     };
1825 
1826     const VkFormat depthStencilFormatRange[] = {
1827         VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,         VK_FORMAT_S8_UINT,
1828         VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_D32_SFLOAT_S8_UINT,
1829     };
1830 
1831     // Minimal set of formats to cover depth and stencil
1832     const VkFormat depthStencilReducedFormatRange[] = {
1833         VK_FORMAT_D16_UNORM,         //!< Must be supported
1834         VK_FORMAT_D24_UNORM_S8_UINT, //!< Either this, or the next one must be supported
1835         VK_FORMAT_D32_SFLOAT_S8_UINT,
1836     };
1837 
1838     struct SampleCase
1839     {
1840         VkSampleCountFlagBits colorSamples;
1841         VkSampleCountFlagBits depthStencilSamples;
1842     };
1843 
1844     // Currently supported EQAA cases
1845     static const SampleCase singlePassCases[] = {
1846         // Less color than depth/stencil
1847         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},  {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1848         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},  {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_16_BIT},
1849         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},  {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1850         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1851         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT},
1852     };
1853 
1854     // Multi-subpass cases
1855 
1856     static const SampleCase caseSubpassIncreaseColor_1[] = {
1857         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1858         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1859     };
1860     static const SampleCase caseSubpassIncreaseColor_2[] = {
1861         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1862         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1863         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1864     };
1865     static const SampleCase caseSubpassDecreaseColor_1[] = {
1866         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1867         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1868     };
1869     static const SampleCase caseSubpassDecreaseColor_2[] = {
1870         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1871         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1872         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1873     };
1874     static const SampleCase caseSubpassIncreaseCoverage_1[] = {
1875         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1876         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1877     };
1878     static const SampleCase caseSubpassIncreaseCoverage_2[] = {
1879         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1880         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1881         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1882     };
1883     static const SampleCase caseSubpassDecreaseCoverage_1[] = {
1884         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1885         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1886     };
1887     static const SampleCase caseSubpassDecreaseCoverage_2[] = {
1888         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1889         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1890         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1891     };
1892 
1893     static const struct
1894     {
1895         const char *const caseName;
1896         const uint32_t numSampleCases;
1897         const SampleCase *pSampleCase;
1898     } subpassCases[] = {
1899         {"multi_subpass_decrease_color_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_1), caseSubpassDecreaseColor_1},
1900         {"multi_subpass_decrease_color_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_2), caseSubpassDecreaseColor_2},
1901         {"multi_subpass_decrease_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_1),
1902          caseSubpassDecreaseCoverage_1},
1903         {"multi_subpass_decrease_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_2),
1904          caseSubpassDecreaseCoverage_2},
1905         {"multi_subpass_increase_color_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_1), caseSubpassIncreaseColor_1},
1906         {"multi_subpass_increase_color_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_2), caseSubpassIncreaseColor_2},
1907         {"multi_subpass_increase_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_1),
1908          caseSubpassIncreaseCoverage_1},
1909         {"multi_subpass_increase_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_2),
1910          caseSubpassIncreaseCoverage_2},
1911     };
1912 
1913     // Test 1: Per-sample expected value check
1914     {
1915         MovePtr<tcu::TestCaseGroup> standardLocationsGroup(
1916             new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_standard_locations"));
1917         MovePtr<tcu::TestCaseGroup> programmableLocationsGroup(
1918             new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_programmable_locations"));
1919 
1920         tcu::TestCaseGroup *locationsGroups[2] = {standardLocationsGroup.get(), programmableLocationsGroup.get()};
1921 
1922         for (uint32_t groupNdx = 0u; groupNdx < DE_LENGTH_OF_ARRAY(locationsGroups); ++groupNdx)
1923         {
1924             // Single subpass cases
1925             for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
1926             {
1927                 VerifySamples::TestParams::SampleCount samples;
1928                 samples.numColorSamples        = singlePassCases[caseNdx].colorSamples;
1929                 samples.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples;
1930                 samples.numCoverageSamples     = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1931 
1932                 VerifySamples::TestParams params;
1933                 params.pipelineConstructionType = pipelineConstructionType;
1934                 params.perSubpassSamples.push_back(samples);
1935                 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1936                 params.useFragmentShadingRate         = useFragmentShadingRate;
1937 
1938                 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1939                     new tcu::TestCaseGroup(rootGroup->getTestContext(),
1940                                            getSampleCountGroupName(samples.numCoverageSamples, samples.numColorSamples,
1941                                                                    samples.numDepthStencilSamples)
1942                                                .c_str()));
1943 
1944                 for (const VkFormat *pDepthStencilFormat = depthStencilFormatRange;
1945                      pDepthStencilFormat != DE_ARRAY_END(depthStencilFormatRange); ++pDepthStencilFormat)
1946                     for (const VkFormat *pColorFormat = colorFormatRange;
1947                          pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1948                     {
1949                         params.colorFormat        = *pColorFormat;
1950                         params.depthStencilFormat = *pDepthStencilFormat;
1951 
1952                         addFunctionCaseWithPrograms(
1953                             sampleCaseGroup.get(),
1954                             getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1955                             VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1956                     }
1957 
1958                 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1959             }
1960 
1961             // Multi subpass cases
1962             for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(subpassCases); ++caseNdx)
1963             {
1964                 VerifySamples::TestParams params;
1965                 params.pipelineConstructionType       = pipelineConstructionType;
1966                 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1967                 params.useFragmentShadingRate         = useFragmentShadingRate;
1968 
1969                 for (uint32_t subpassNdx = 0; subpassNdx < subpassCases[caseNdx].numSampleCases; ++subpassNdx)
1970                 {
1971                     VerifySamples::TestParams::SampleCount samples;
1972                     samples.numColorSamples        = subpassCases[caseNdx].pSampleCase[subpassNdx].colorSamples;
1973                     samples.numDepthStencilSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].depthStencilSamples;
1974                     samples.numCoverageSamples     = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1975                     params.perSubpassSamples.push_back(samples);
1976                 }
1977 
1978                 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1979                     new tcu::TestCaseGroup(rootGroup->getTestContext(), subpassCases[caseNdx].caseName));
1980 
1981                 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
1982                      pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
1983                     for (const VkFormat *pColorFormat = colorFormatRange;
1984                          pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1985                     {
1986                         params.colorFormat        = *pColorFormat;
1987                         params.depthStencilFormat = *pDepthStencilFormat;
1988 
1989                         addFunctionCaseWithPrograms(
1990                             sampleCaseGroup.get(),
1991                             getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1992                             VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1993                     }
1994 
1995                 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1996             }
1997         }
1998 
1999         rootGroup->addChild(standardLocationsGroup.release());
2000         rootGroup->addChild(programmableLocationsGroup.release());
2001     }
2002 
2003     // Test 2: Shader built-ins check
2004     if (!useFragmentShadingRate)
2005     {
2006         MovePtr<tcu::TestCaseGroup> builtinsGroup(
2007             new tcu::TestCaseGroup(rootGroup->getTestContext(), "shader_builtins"));
2008 
2009         for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
2010         {
2011             ShaderBuiltins::TestParams params;
2012             params.pipelineConstructionType = pipelineConstructionType;
2013             params.numColorSamples          = singlePassCases[caseNdx].colorSamples;
2014             params.numDepthStencilSamples   = singlePassCases[caseNdx].depthStencilSamples;
2015             params.numCoverageSamples       = de::max(params.numColorSamples, params.numDepthStencilSamples);
2016 
2017             MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(
2018                 rootGroup->getTestContext(), getSampleCountGroupName(params.numCoverageSamples, params.numColorSamples,
2019                                                                      params.numDepthStencilSamples)
2020                                                  .c_str()));
2021 
2022             for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
2023                  pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
2024                 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange);
2025                      ++pColorFormat)
2026                 {
2027                     params.colorFormat        = *pColorFormat;
2028                     params.depthStencilFormat = *pDepthStencilFormat;
2029 
2030                     addFunctionCaseWithPrograms(
2031                         sampleCaseGroup.get(), getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
2032                         ShaderBuiltins::checkRequirements, ShaderBuiltins::initPrograms, ShaderBuiltins::test, params);
2033                 }
2034 
2035             builtinsGroup->addChild(sampleCaseGroup.release());
2036         }
2037 
2038         rootGroup->addChild(builtinsGroup.release());
2039     }
2040 }
2041 
2042 } // namespace
2043 
createMultisampleMixedAttachmentSamplesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)2044 tcu::TestCaseGroup *createMultisampleMixedAttachmentSamplesTests(tcu::TestContext &testCtx,
2045                                                                  PipelineConstructionType pipelineConstructionType,
2046                                                                  bool useFragmentShadingRate)
2047 {
2048     // Test a graphics pipeline with varying sample count per color and depth/stencil attachments
2049     return createTestGroup(testCtx, "mixed_attachment_samples", createMixedAttachmentSamplesTestsInGroup,
2050                            pipelineConstructionType, useFragmentShadingRate);
2051 }
2052 
2053 } // namespace pipeline
2054 } // namespace vkt
2055