Check sampleRateShading for sample_qualifier_distinct_values.* tests
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineMultisampleInterpolationTests.cpp
1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*
20 * \file vktPipelineMultisampleInterpolationTests.cpp
21 * \brief Multisample Interpolation Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineMultisampleInterpolationTests.hpp"
25 #include "vktPipelineMultisampleTestsUtil.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "tcuTestLog.hpp"
29
30 #include <set>
31
32 namespace vkt
33 {
34 namespace pipeline
35 {
36 namespace multisample
37 {
38
39 using namespace vk;
40
41 struct ImageMSParams
42 {
43         ImageMSParams(const VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {}
44
45         VkSampleCountFlagBits   numSamples;
46         tcu::UVec3                              imageSize;
47 };
48
49 class MSInterpolationCaseBase : public TestCase
50 {
51 public:
52         MSInterpolationCaseBase (tcu::TestContext&              testCtx,
53                                                          const std::string&             name,
54                                                          const ImageMSParams&   imageMSParams)
55                 : TestCase(testCtx, name, "")
56                 , m_imageMSParams(imageMSParams)
57         {}
58
59 protected:
60         const ImageMSParams m_imageMSParams;
61 };
62
63 typedef MSInterpolationCaseBase* (*MSInterpolationCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams);
64
65 class MSInterpolationInstanceBase : public TestInstance
66 {
67 public:
68                                                                 MSInterpolationInstanceBase     (Context&                                                       context,
69                                                                                                                          const ImageMSParams&                           imageMSParams)
70                 : TestInstance          (context)
71                 , m_imageMSParams       (imageMSParams)
72                 , m_imageType           (IMAGE_TYPE_2D)
73                 , m_imageFormat         (tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNORM_INT8))
74         {}
75
76         tcu::TestStatus                         iterate                                         (void);
77
78 protected:
79
80         typedef std::vector<VkVertexInputAttributeDescription> VertexAttribDescVec;
81
82         struct VertexDataDesc
83         {
84                 VkPrimitiveTopology     primitiveTopology;
85                 deUint32                        verticesCount;
86                 deUint32                        dataStride;
87                 VkDeviceSize            dataSize;
88                 VertexAttribDescVec     vertexAttribDescVec;
89         };
90
91         void                                            validateImageSize                       (const InstanceInterface&                       instance,
92                                                                                                                          const VkPhysicalDevice                         physicalDevice,
93                                                                                                                          const ImageType                                        imageType,
94                                                                                                                          const tcu::UVec3&                                      imageSize) const;
95
96         void                                            validateImageFeatureFlags       (const InstanceInterface&                       instance,
97                                                                                                                          const VkPhysicalDevice                         physicalDevice,
98                                                                                                                          const VkFormat                                         format,
99                                                                                                                          const VkFormatFeatureFlags                     featureFlags) const;
100
101         void                                            validateImageInfo                       (const InstanceInterface&                       instance,
102                                                                                                                          const VkPhysicalDevice                         physicalDevice,
103                                                                                                                          const VkImageCreateInfo&                       imageInfo) const;
104
105         virtual VertexDataDesc          getVertexDataDescripton         (void) const = 0;
106
107         virtual void                            uploadVertexData                        (const Allocation&                                      vertexBufferAllocation,
108                                                                                                                          const VertexDataDesc&                          vertexDataDescripton) const = 0;
109
110         virtual tcu::TestStatus         verifyResolvedImage                     (const tcu::ConstPixelBufferAccess&     imageData) const = 0;
111 protected:
112         const ImageMSParams                     m_imageMSParams;
113         const ImageType                         m_imageType;
114         const tcu::TextureFormat        m_imageFormat;
115 };
116
117 void MSInterpolationInstanceBase::validateImageSize (const InstanceInterface&   instance,
118                                                                                                          const VkPhysicalDevice         physicalDevice,
119                                                                                                          const ImageType                        imageType,
120                                                                                                          const tcu::UVec3&                      imageSize) const
121 {
122         const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
123
124         bool isImageSizeValid = true;
125
126         switch (imageType)
127         {
128                 case IMAGE_TYPE_1D:
129                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
130                         break;
131                 case IMAGE_TYPE_1D_ARRAY:
132                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
133                                                                 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
134                         break;
135                 case IMAGE_TYPE_2D:
136                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
137                                                                 imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
138                         break;
139                 case IMAGE_TYPE_2D_ARRAY:
140                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
141                                                                 imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
142                                                                 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
143                         break;
144                 case IMAGE_TYPE_CUBE:
145                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
146                                                                 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
147                         break;
148                 case IMAGE_TYPE_CUBE_ARRAY:
149                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
150                                                                 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
151                                                                 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
152                         break;
153                 case IMAGE_TYPE_3D:
154                         isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
155                                                                 imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
156                                                                 imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
157                         break;
158                 default:
159                         DE_FATAL("Unknown image type");
160         }
161
162         if (!isImageSizeValid)
163         {
164                 std::ostringstream      notSupportedStream;
165
166                 notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl;
167
168                 const std::string notSupportedString = notSupportedStream.str();
169
170                 TCU_THROW(NotSupportedError, notSupportedString.c_str());
171         }
172 }
173
174 void MSInterpolationInstanceBase::validateImageFeatureFlags     (const InstanceInterface&       instance,
175                                                                                                                          const VkPhysicalDevice         physicalDevice,
176                                                                                                                          const VkFormat                         format,
177                                                                                                                          const VkFormatFeatureFlags     featureFlags) const
178 {
179         const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
180
181         if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags)
182         {
183                 std::ostringstream      notSupportedStream;
184
185                 notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl;
186
187                 const std::string notSupportedString = notSupportedStream.str();
188
189                 TCU_THROW(NotSupportedError, notSupportedString.c_str());
190         }
191 }
192
193 void MSInterpolationInstanceBase::validateImageInfo     (const InstanceInterface&       instance,
194                                                                                                          const VkPhysicalDevice         physicalDevice,
195                                                                                                          const VkImageCreateInfo&       imageInfo) const
196 {
197         VkImageFormatProperties imageFormatProps;
198         instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps);
199
200         if (imageFormatProps.maxExtent.width  < imageInfo.extent.width  ||
201                 imageFormatProps.maxExtent.height < imageInfo.extent.height ||
202                 imageFormatProps.maxExtent.depth  < imageInfo.extent.depth)
203         {
204                 std::ostringstream      notSupportedStream;
205
206                 notSupportedStream      << "Image extent ("
207                                                         << imageInfo.extent.width  << ", "
208                                                         << imageInfo.extent.height << ", "
209                                                         << imageInfo.extent.depth
210                                                         << ") exceeds allowed maximum ("
211                                                         << imageFormatProps.maxExtent.width <<  ", "
212                                                         << imageFormatProps.maxExtent.height << ", "
213                                                         << imageFormatProps.maxExtent.depth
214                                                         << ")"
215                                                         << std::endl;
216
217                 const std::string notSupportedString = notSupportedStream.str();
218
219                 TCU_THROW(NotSupportedError, notSupportedString.c_str());
220         }
221
222         if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers)
223         {
224                 std::ostringstream      notSupportedStream;
225
226                 notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl;
227
228                 const std::string notSupportedString = notSupportedStream.str();
229
230                 TCU_THROW(NotSupportedError, notSupportedString.c_str());
231         }
232
233         if (!(imageFormatProps.sampleCounts & imageInfo.samples))
234         {
235                 std::ostringstream      notSupportedStream;
236
237                 notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl;
238
239                 const std::string notSupportedString = notSupportedStream.str();
240
241                 TCU_THROW(NotSupportedError, notSupportedString.c_str());
242         }
243 }
244
245 tcu::TestStatus MSInterpolationInstanceBase::iterate (void)
246 {
247         const InstanceInterface&                instance                        = m_context.getInstanceInterface();
248         const DeviceInterface&                  deviceInterface         = m_context.getDeviceInterface();
249         const VkDevice                                  device                          = m_context.getDevice();
250         const VkPhysicalDevice                  physicalDevice          = m_context.getPhysicalDevice();
251         const VkPhysicalDeviceFeatures& features                        = m_context.getDeviceFeatures();
252         Allocator&                                              allocator                       = m_context.getDefaultAllocator();
253         const VkQueue                                   queue                           = m_context.getUniversalQueue();
254         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
255
256         VkImageCreateInfo                               imageMSInfo;
257         VkImageCreateInfo                               imageRSInfo;
258
259         // Check if image size does not exceed device limits
260         validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
261
262         // Check if device supports image format as color attachment
263         validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
264
265         imageMSInfo.sType                                       = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
266         imageMSInfo.pNext                                       = DE_NULL;
267         imageMSInfo.flags                                       = 0u;
268         imageMSInfo.imageType                           = mapImageType(m_imageType);
269         imageMSInfo.format                                      = mapTextureFormat(m_imageFormat);
270         imageMSInfo.extent                                      = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
271         imageMSInfo.arrayLayers                         = getNumLayers(m_imageType, m_imageMSParams.imageSize);
272         imageMSInfo.mipLevels                           = 1u;
273         imageMSInfo.samples                                     = m_imageMSParams.numSamples;
274         imageMSInfo.tiling                                      = VK_IMAGE_TILING_OPTIMAL;
275         imageMSInfo.initialLayout                       = VK_IMAGE_LAYOUT_UNDEFINED;
276         imageMSInfo.usage                                       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
277         imageMSInfo.sharingMode                         = VK_SHARING_MODE_EXCLUSIVE;
278         imageMSInfo.queueFamilyIndexCount       = 0u;
279         imageMSInfo.pQueueFamilyIndices         = DE_NULL;
280
281         if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
282         {
283                 imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
284         }
285
286         validateImageInfo(instance, physicalDevice, imageMSInfo);
287
288         const de::UniquePtr<Image> imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
289
290         imageRSInfo                     = imageMSInfo;
291         imageRSInfo.samples     = VK_SAMPLE_COUNT_1_BIT;
292
293         validateImageInfo(instance, physicalDevice, imageRSInfo);
294
295         const de::UniquePtr<Image> imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
296
297         // Create render pass
298         const VkAttachmentDescription attachmentMSDesc =
299         {
300                 (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
301                 imageMSInfo.format,                                                     // VkFormat                                                     format;
302                 imageMSInfo.samples,                                            // VkSampleCountFlagBits                        samples;
303                 VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp                           loadOp;
304                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
305                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
306                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
307                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
308                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout;
309         };
310
311         const VkAttachmentDescription attachmentRSDesc =
312         {
313                 (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
314                 imageRSInfo.format,                                                     // VkFormat                                                     format;
315                 imageRSInfo.samples,                                            // VkSampleCountFlagBits                        samples;
316                 VK_ATTACHMENT_LOAD_OP_CLEAR,                    // VkAttachmentLoadOp                           loadOp;
317                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
318                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
319                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
320                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
321                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout;
322         };
323
324         const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc };
325
326         const VkAttachmentReference attachmentMSRef =
327         {
328                 0u,                                                                                     // deUint32                     attachment;
329                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
330         };
331
332         const VkAttachmentReference attachmentRSRef =
333         {
334                 1u,                                                                                     // deUint32                     attachment;
335                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
336         };
337
338         const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef;
339
340         const VkSubpassDescription subpassDescription =
341         {
342                 (VkSubpassDescriptionFlags)0u,                                          // VkSubpassDescriptionFlags            flags;
343                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
344                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
345                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
346                 1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
347                 &attachmentMSRef,                                                                       // const VkAttachmentReference*         pColorAttachments;
348                 resolveAttachment,                                                              // const VkAttachmentReference*         pResolveAttachments;
349                 DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
350                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
351                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
352         };
353
354         const VkRenderPassCreateInfo renderPassInfo =
355         {
356                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
357                 DE_NULL,                                                                                        // const void*                                          pNext;
358                 (VkRenderPassCreateFlags)0u,                                            // VkRenderPassCreateFlags                      flags;
359                 2u,                                                                                                     // deUint32                                                     attachmentCount;
360                 attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
361                 1u,                                                                                                     // deUint32                                                     subpassCount;
362                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
363                 0u,                                                                                                     // deUint32                                                     dependencyCount;
364                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
365         };
366
367         const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
368
369         const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
370
371         // Create color attachments image views
372         const Unique<VkImageView> imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
373         const Unique<VkImageView> imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
374
375         const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView };
376
377         // Create framebuffer
378         const VkFramebufferCreateInfo framebufferInfo =
379         {
380                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                             sType;
381                 DE_NULL,                                                                        // const void*                                 pNext;
382                 (VkFramebufferCreateFlags)0u,                           // VkFramebufferCreateFlags                    flags;
383                 *renderPass,                                                            // VkRenderPass                                renderPass;
384                 2u,                                                                                     // uint32_t                                    attachmentCount;
385                 attachmentsViews,                                                       // const VkImageView*                          pAttachments;
386                 imageMSInfo.extent.width,                                       // uint32_t                                    width;
387                 imageMSInfo.extent.height,                                      // uint32_t                                    height;
388                 imageMSInfo.arrayLayers,                                        // uint32_t                                    layers;
389         };
390
391         const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
392
393         // Create pipeline layout
394         const VkPipelineLayoutCreateInfo pipelineLayoutParams =
395         {
396                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
397                 DE_NULL,                                                                                        // const void*                                          pNext;
398                 (VkPipelineLayoutCreateFlags)0u,                                        // VkPipelineLayoutCreateFlags          flags;
399                 0u,                                                                                                     // deUint32                                                     setLayoutCount;
400                 DE_NULL,                                                                                        // const VkDescriptorSetLayout*         pSetLayouts;
401                 0u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
402                 DE_NULL,                                                                                        // const VkPushConstantRange*           pPushConstantRanges;
403         };
404
405         const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams));
406
407         // Create vertex attributes data
408         const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
409
410         de::SharedPtr<Buffer> vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
411         const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
412
413         uploadVertexData(vertexBufferAllocation, vertexDataDesc);
414
415         flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), vertexDataDesc.dataSize);
416
417         const VkVertexInputBindingDescription vertexBinding =
418         {
419                 0u,                                                     // deUint32                             binding;
420                 vertexDataDesc.dataStride,      // deUint32                             stride;
421                 VK_VERTEX_INPUT_RATE_VERTEX     // VkVertexInputRate    inputRate;
422         };
423
424         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
425         {
426                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,                      // VkStructureType                             sType;
427                 DE_NULL,                                                                                                                        // const void*                                 pNext;
428                 (VkPipelineVertexInputStateCreateFlags)0u,                                                      // VkPipelineVertexInputStateCreateFlags       flags;
429                 1u,                                                                                                                                     // uint32_t                                    vertexBindingDescriptionCount;
430                 &vertexBinding,                                                                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
431                 static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()),       // uint32_t                                    vertexAttributeDescriptionCount;
432                 dataPointer(vertexDataDesc.vertexAttribDescVec),                                        // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
433         };
434
435         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
436         {
437                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
438                 DE_NULL,                                                                                                                // const void*                                 pNext;
439                 (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags     flags;
440                 vertexDataDesc.primitiveTopology,                                                               // VkPrimitiveTopology                         topology;
441                 VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
442         };
443
444         const VkViewport viewport =
445         {
446                 0.0f, 0.0f,
447                 static_cast<float>(imageMSInfo.extent.width), static_cast<float>(imageMSInfo.extent.height),
448                 0.0f, 1.0f
449         };
450
451         const VkRect2D scissor =
452         {
453                 makeOffset2D(0, 0),
454                 makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
455         };
456
457         const VkPipelineViewportStateCreateInfo viewportStateInfo =
458         {
459                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
460                 DE_NULL,                                                                                                                // const void*                                 pNext;
461                 (VkPipelineViewportStateCreateFlags)0u,                                                 // VkPipelineViewportStateCreateFlags          flags;
462                 1u,                                                                                                                             // uint32_t                                    viewportCount;
463                 &viewport,                                                                                                              // const VkViewport*                           pViewports;
464                 1u,                                                                                                                             // uint32_t                                    scissorCount;
465                 &scissor,                                                                                                               // const VkRect2D*                             pScissors;
466         };
467
468         const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
469         {
470                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
471                 DE_NULL,                                                                                                                // const void*                              pNext;
472                 (VkPipelineRasterizationStateCreateFlags)0u,                                    // VkPipelineRasterizationStateCreateFlags  flags;
473                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
474                 VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
475                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
476                 VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
477                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
478                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
479                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
480                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
481                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
482                 1.0f,                                                                                                                   // float                                                                        lineWidth;
483         };
484
485         const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
486         {
487                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
488                 DE_NULL,                                                                                                                // const void*                                                          pNext;
489                 (VkPipelineMultisampleStateCreateFlags)0u,                                              // VkPipelineMultisampleStateCreateFlags        flags;
490                 imageMSInfo.samples,                                                                                    // VkSampleCountFlagBits                                        rasterizationSamples;
491                 features.sampleRateShading,                                                                             // VkBool32                                                                     sampleShadingEnable;
492                 1.0f,                                                                                                                   // float                                                                        minSampleShading;
493                 DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
494                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
495                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToOneEnable;
496         };
497
498         const VkStencilOpState stencilOpState = makeStencilOpState
499         (
500                 VK_STENCIL_OP_KEEP,             // stencil fail
501                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
502                 VK_STENCIL_OP_KEEP,             // depth only fail
503                 VK_COMPARE_OP_ALWAYS,   // compare op
504                 0u,                                             // compare mask
505                 0u,                                             // write mask
506                 0u                                              // reference
507         );
508
509         const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo =
510         {
511                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
512                 DE_NULL,                                                                                                                // const void*                                                          pNext;
513                 (VkPipelineDepthStencilStateCreateFlags)0u,                                             // VkPipelineDepthStencilStateCreateFlags       flags;
514                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
515                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
516                 VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
517                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
518                 VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
519                 stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
520                 stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
521                 0.0f,                                                                                                                   // float                                                                        minDepthBounds;
522                 1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
523         };
524
525         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
526
527         const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
528         {
529                 VK_FALSE,                                                                                                               // VkBool32                                     blendEnable;
530                 VK_BLEND_FACTOR_SRC_ALPHA,                                                                              // VkBlendFactor                        srcColorBlendFactor;
531                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                                    // VkBlendFactor                        dstColorBlendFactor;
532                 VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            colorBlendOp;
533                 VK_BLEND_FACTOR_SRC_ALPHA,                                                                              // VkBlendFactor                        srcAlphaBlendFactor;
534                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                                    // VkBlendFactor                        dstAlphaBlendFactor;
535                 VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            alphaBlendOp;
536                 colorComponentsAll,                                                                                             // VkColorComponentFlags        colorWriteMask;
537         };
538
539         const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
540         {
541                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
542                 DE_NULL,                                                                                                                // const void*                                                                  pNext;
543                 (VkPipelineColorBlendStateCreateFlags)0u,                                               // VkPipelineColorBlendStateCreateFlags                 flags;
544                 VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
545                 VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
546                 1u,                                                                                                                             // deUint32                                                                             attachmentCount;
547                 &colorBlendAttachmentState,                                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
548                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
549         };
550
551         const Unique<VkShaderModule> vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0));
552
553         const VkPipelineShaderStageCreateInfo vsShaderStageInfo =
554         {
555                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
556                 DE_NULL,                                                                                                                // const void*                                                  pNext;
557                 (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
558                 VK_SHADER_STAGE_VERTEX_BIT,                                                                             // VkShaderStageFlagBits                                stage;
559                 *vsModule,                                                                                                              // VkShaderModule                                               module;
560                 "main",                                                                                                                 // const char*                                                  pName;
561                 DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
562         };
563
564         const Unique<VkShaderModule> fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0));
565
566         const VkPipelineShaderStageCreateInfo fsShaderStageInfo =
567         {
568                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
569                 DE_NULL,                                                                                                                // const void*                                                  pNext;
570                 (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
571                 VK_SHADER_STAGE_FRAGMENT_BIT,                                                                   // VkShaderStageFlagBits                                stage;
572                 *fsModule,                                                                                                              // VkShaderModule                                               module;
573                 "main",                                                                                                                 // const char*                                                  pName;
574                 DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
575         };
576
577         const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo };
578
579         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
580         {
581                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                // VkStructureType                                                                      sType;
582                 DE_NULL,                                                                                                                // const void*                                                                          pNext;
583                 (VkPipelineCreateFlags)0,                                                                               // VkPipelineCreateFlags                                                        flags;
584                 2u,                                                                                                                             // deUint32                                                                                     stageCount;
585                 shaderStageInfos,                                                                                               // const VkPipelineShaderStageCreateInfo*                       pStages;
586                 &vertexInputStateInfo,                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
587                 &inputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
588                 DE_NULL,                                                                                                                // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
589                 &viewportStateInfo,                                                                                             // const VkPipelineViewportStateCreateInfo*                     pViewportState;
590                 &rasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
591                 &multisampleStateInfo,                                                                                  // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
592                 &depthStencilStateInfo,                                                                                 // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
593                 &colorBlendStateInfo,                                                                                   // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
594                 DE_NULL,                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
595                 *pipelineLayout,                                                                                                // VkPipelineLayout                                                                     layout;
596                 *renderPass,                                                                                                    // VkRenderPass                                                                         renderPass;
597                 0u,                                                                                                                             // deUint32                                                                                     subpass;
598                 DE_NULL,                                                                                                                // VkPipeline                                                                           basePipelineHandle;
599                 0u,                                                                                                                             // deInt32                                                                                      basePipelineIndex;
600         };
601
602         // Create graphics pipeline
603         const Unique<VkPipeline> graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo));
604
605         // Create command buffer for compute and transfer oparations
606         const Unique<VkCommandPool>       commandPool(createCommandPool(deviceInterface, device, (VkCommandPoolCreateFlags)VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
607         const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
608
609         // Start recording commands
610         beginCommandBuffer(deviceInterface, *commandBuffer);
611
612         {
613                 VkImageMemoryBarrier imageOutputAttachmentBarriers[2];
614
615                 imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
616                 (
617                         0u,
618                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
619                         VK_IMAGE_LAYOUT_UNDEFINED,
620                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
621                         **imageMS,
622                         fullImageRange
623                 );
624
625                 imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
626                 (
627                         0u,
628                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
629                         VK_IMAGE_LAYOUT_UNDEFINED,
630                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
631                         **imageRS,
632                         fullImageRange
633                 );
634
635                 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers);
636         }
637
638         {
639                 const VkDeviceSize vertexStartOffset = 0u;
640
641                 std::vector<VkClearValue> clearValues;
642                 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
643                 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
644
645                 const vk::VkRect2D renderArea =
646                 {
647                         makeOffset2D(0u, 0u),
648                         makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
649                 };
650
651                 // Begin render pass
652                 const VkRenderPassBeginInfo renderPassBeginInfo =
653                 {
654                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
655                         DE_NULL,                                                                                // const void*             pNext;
656                         *renderPass,                                                                            // VkRenderPass            renderPass;
657                         *framebuffer,                                                                   // VkFramebuffer           framebuffer;
658                         renderArea,                                                                             // VkRect2D                renderArea;
659                         static_cast<deUint32>(clearValues.size()),              // deUint32                clearValueCount;
660                         &clearValues[0],                                                                // const VkClearValue*     pClearValues;
661                 };
662
663                 deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
664
665                 // Bind graphics pipeline
666                 deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
667
668                 // Bind vertex buffer
669                 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
670
671                 // Draw full screen quad
672                 deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
673
674                 // End render pass
675                 deviceInterface.cmdEndRenderPass(*commandBuffer);
676         }
677
678         const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS;
679
680         {
681                 const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier
682                 (
683                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
684                         VK_ACCESS_TRANSFER_READ_BIT,
685                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
686                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
687                         sourceImage,
688                         fullImageRange
689                 );
690
691                 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier);
692         }
693
694         // Copy data from resolve image to buffer
695         const deUint32                          imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels);
696
697         const VkBufferCreateInfo        bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
698         const de::UniquePtr<Buffer>     bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
699
700         {
701                 const VkBufferImageCopy bufferImageCopy =
702                 {
703                         0u,                                                                                                                                                                             //      VkDeviceSize                            bufferOffset;
704                         0u,                                                                                                                                                                             //      deUint32                                        bufferRowLength;
705                         0u,                                                                                                                                                                             //      deUint32                                        bufferImageHeight;
706                         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), //      VkImageSubresourceLayers        imageSubresource;
707                         makeOffset3D(0, 0, 0),                                                                                                                                  //      VkOffset3D                                      imageOffset;
708                         imageRSInfo.extent,                                                                                                                                             //      VkExtent3D                                      imageExtent;
709                 };
710
711                 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
712         }
713
714         {
715                 const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
716                 (
717                         VK_ACCESS_TRANSFER_WRITE_BIT,
718                         VK_ACCESS_HOST_READ_BIT,
719                         bufferRS->get(),
720                         0u,
721                         imageRSSizeInBytes
722                 );
723
724                 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
725         }
726
727         // End recording commands
728         VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer));
729
730         // Submit commands for execution and wait for completion
731         submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
732
733         // Retrieve data from buffer to host memory
734         const Allocation& bufferRSAllocation = bufferRS->getAllocation();
735
736         invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), imageRSSizeInBytes);
737
738         const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
739                                                                                                         imageRSInfo.extent.width,
740                                                                                                         imageRSInfo.extent.height,
741                                                                                                         imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
742                                                                                                         bufferRSAllocation.getHostPtr());
743
744         std::stringstream imageName;
745         imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
746
747         m_context.getTestContext().getLog()
748                 << tcu::TestLog::Section(imageName.str(), imageName.str())
749                 << tcu::LogImage("image", "", bufferRSData)
750                 << tcu::TestLog::EndSection;
751
752         return verifyResolvedImage(bufferRSData);
753 }
754
755 class MSInstanceDistinctValues : public MSInterpolationInstanceBase
756 {
757 public:
758                                         MSInstanceDistinctValues(Context&                               context,
759                                                                                          const ImageMSParams&   imageMSParams)
760         : MSInterpolationInstanceBase(context, imageMSParams) {}
761
762         VertexDataDesc  getVertexDataDescripton (void) const;
763         void                    uploadVertexData                (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
764         tcu::TestStatus verifyResolvedImage             (const tcu::ConstPixelBufferAccess&     imageData) const;
765
766 protected:
767         struct VertexData
768         {
769                 VertexData(const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
770
771                 tcu::Vec4 positionNdc;
772         };
773 };
774
775 MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexDataDescripton (void) const
776 {
777         VertexDataDesc vertexDataDesc;
778
779         vertexDataDesc.verticesCount            = 3u;
780         vertexDataDesc.dataStride                       = sizeof(VertexData);
781         vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
782         vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
783
784         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
785         {
786                 0u,                                                                             // deUint32     location;
787                 0u,                                                                             // deUint32     binding;
788                 VK_FORMAT_R32G32B32A32_SFLOAT,                  // VkFormat     format;
789                 DE_OFFSET_OF(VertexData, positionNdc),  // deUint32     offset;
790         };
791
792         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
793
794         return vertexDataDesc;
795 }
796
797 void MSInstanceDistinctValues::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
798 {
799         std::vector<VertexData> vertices;
800
801         vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f)));
802         vertices.push_back(VertexData(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
803         vertices.push_back(VertexData(tcu::Vec4( 4.0f,-1.0f, 0.0f, 1.0f)));
804
805         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
806 }
807
808 tcu::TestStatus MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
809 {
810         const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
811
812         std::vector<tcu::IVec4> distinctValues;
813
814         for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
815         for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
816         for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
817         {
818                 const tcu::IVec4 pixel = imageData.getPixelInt(x, y, z);
819
820                 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
821                         distinctValues.push_back(pixel);
822         }
823
824         if (distinctValues.size() >= distinctValuesExpected)
825                 return tcu::TestStatus::pass("Passed");
826         else
827                 return tcu::TestStatus::fail("Failed");
828 }
829
830 class MSCaseSampleQualifierDistinctValues : public MSInterpolationCaseBase
831 {
832 public:
833                                         MSCaseSampleQualifierDistinctValues     (tcu::TestContext&              testCtx,
834                                                                                                                  const std::string&             name,
835                                                                                                                  const ImageMSParams&   imageMSParams)
836         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
837
838         void                    init                                                            (void);
839         void                    initPrograms                                            (vk::SourceCollections& programCollection) const;
840         TestInstance*   createInstance                                          (Context&                               context) const;
841 };
842
843 MSInterpolationCaseBase* createMSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
844 {
845         return new MSCaseSampleQualifierDistinctValues(testCtx, name, imageMSParams);
846 }
847
848 void MSCaseSampleQualifierDistinctValues::init (void)
849 {
850         m_testCtx.getLog()
851                 << tcu::TestLog::Message
852                 << "Verifying that a sample qualified varying is given different values for different samples.\n"
853                 << "    Render full screen traingle with quadratic function defining red/green color pattern division.\n"
854                 << "    => Resulting image should contain n+1 different colors, where n = sample count.\n"
855                 << tcu::TestLog::EndMessage;
856
857         MSInterpolationCaseBase::init();
858 }
859
860 void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
861 {
862         // Create vertex shader
863         std::ostringstream vs;
864
865         vs << "#version 440\n"
866                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
867                 << "\n"
868                 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
869                 << "\n"
870                 << "out gl_PerVertex {\n"
871                 << "    vec4  gl_Position;\n"
872                 << "};\n"
873                 << "void main (void)\n"
874                 << "{\n"
875                 << "    gl_Position                     = vs_in_position_ndc;\n"
876                 << "    vs_out_position_ndc = vs_in_position_ndc;\n"
877                 << "}\n";
878
879         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
880
881         // Create fragment shader
882         std::ostringstream fs;
883
884         fs << "#version 440\n"
885                 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
886                 << "\n"
887                 << "layout(location = 0) out vec2 fs_out_color;\n"
888                 << "\n"
889                 << "void main (void)\n"
890                 << "{\n"
891                 << "    if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
892                 << "            fs_out_color = vec2(1.0, 0.0);\n"
893                 << "    else\n"
894                 << "            fs_out_color = vec2(0.0, 1.0);\n"
895                 << "}\n";
896
897         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
898 }
899
900 TestInstance* MSCaseSampleQualifierDistinctValues::createInstance (Context& context) const
901 {
902         if (!context.getDeviceFeatures().sampleRateShading)
903                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
904         return new MSInstanceDistinctValues(context, m_imageMSParams);
905 }
906
907 class MSCaseInterpolateAtSampleDistinctValues : public MSInterpolationCaseBase
908 {
909 public:
910                                         MSCaseInterpolateAtSampleDistinctValues (tcu::TestContext&              testCtx,
911                                                                                                                          const std::string&             name,
912                                                                                                                          const ImageMSParams&   imageMSParams)
913         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
914
915         void                    init                                                                    (void);
916         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
917         TestInstance*   createInstance                                                  (Context&                               context) const;
918 };
919
920 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
921 {
922         return new MSCaseInterpolateAtSampleDistinctValues(testCtx, name, imageMSParams);
923 }
924
925 void MSCaseInterpolateAtSampleDistinctValues::init (void)
926 {
927         m_testCtx.getLog()
928                 << tcu::TestLog::Message
929                 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
930                 << "    Render full screen traingle with quadratic function defining red/green color pattern division.\n"
931                 << "    => Resulting image should contain n+1 different colors, where n = sample count.\n"
932                 << tcu::TestLog::EndMessage;
933
934         MSInterpolationCaseBase::init();
935 }
936
937 void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
938 {
939         // Create vertex shader
940         std::ostringstream vs;
941
942         vs << "#version 440\n"
943                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
944                 << "\n"
945                 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
946                 << "\n"
947                 << "out gl_PerVertex {\n"
948                 << "    vec4  gl_Position;\n"
949                 << "};\n"
950                 << "void main (void)\n"
951                 << "{\n"
952                 << "    gl_Position                     = vs_in_position_ndc;\n"
953                 << "    vs_out_position_ndc = vs_in_position_ndc;\n"
954                 << "}\n";
955
956         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
957
958         // Create fragment shader
959         std::ostringstream fs;
960
961         fs << "#version 440\n"
962                 << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
963                 << "\n"
964                 << "layout(location = 0) out vec2 fs_out_color;\n"
965                 << "\n"
966                 << "void main (void)\n"
967                 << "{\n"
968                 << "    const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
969                 << "    if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
970                 << "            fs_out_color = vec2(0.0, 1.0);\n"
971                 << "    else\n"
972                 << "            fs_out_color = vec2(1.0, 0.0);\n"
973                 << "}\n";
974
975         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
976 }
977
978 TestInstance* MSCaseInterpolateAtSampleDistinctValues::createInstance (Context& context) const
979 {
980         if (!context.getDeviceFeatures().sampleRateShading)
981                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
982
983         return new MSInstanceDistinctValues(context, m_imageMSParams);
984 }
985
986 class MSInstanceInterpolateScreenPosition : public MSInterpolationInstanceBase
987 {
988 public:
989                                         MSInstanceInterpolateScreenPosition     (Context&                               context,
990                                                                                                                  const ImageMSParams&   imageMSParams)
991         : MSInterpolationInstanceBase(context, imageMSParams) {}
992
993         VertexDataDesc  getVertexDataDescripton                         (void) const;
994         void                    uploadVertexData                                        (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
995         tcu::TestStatus verifyResolvedImage                                     (const tcu::ConstPixelBufferAccess&     imageData) const;
996
997 protected:
998         struct VertexData
999         {
1000                 VertexData(const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
1001
1002                 tcu::Vec4 positionNdc;
1003                 tcu::Vec2 positionScreen;
1004         };
1005 };
1006
1007 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition::getVertexDataDescripton (void) const
1008 {
1009         VertexDataDesc vertexDataDesc;
1010
1011         vertexDataDesc.verticesCount            = 4u;
1012         vertexDataDesc.dataStride                       = sizeof(VertexData);
1013         vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1014         vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1015
1016         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1017         {
1018                 0u,                                                                                     // deUint32     location;
1019                 0u,                                                                                     // deUint32     binding;
1020                 VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
1021                 DE_OFFSET_OF(VertexData, positionNdc),          // deUint32     offset;
1022         };
1023
1024         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1025
1026         const VkVertexInputAttributeDescription vertexAttribPositionScreen =
1027         {
1028                 1u,                                                                                     // deUint32     location;
1029                 0u,                                                                                     // deUint32     binding;
1030                 VK_FORMAT_R32G32_SFLOAT,                                        // VkFormat     format;
1031                 DE_OFFSET_OF(VertexData, positionScreen),       // deUint32     offset;
1032         };
1033
1034         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
1035
1036         return vertexDataDesc;
1037 }
1038
1039 void MSInstanceInterpolateScreenPosition::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1040 {
1041         const tcu::UVec3 layerSize              = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
1042         const float              screenSizeX    = static_cast<float>(layerSize.x());
1043         const float              screenSizeY    = static_cast<float>(layerSize.y());
1044
1045         std::vector<VertexData> vertices;
1046
1047         vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,                0.0f)));
1048         vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
1049         vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,                screenSizeY)));
1050         vertices.push_back(VertexData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
1051
1052         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1053 }
1054
1055 tcu::TestStatus MSInstanceInterpolateScreenPosition::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1056 {
1057         for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
1058         for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1059         for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
1060         {
1061                 const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1062
1063                 if (firstComponent > 0)
1064                         return tcu::TestStatus::fail("Failed");
1065         }
1066         return tcu::TestStatus::pass("Passed");
1067 }
1068
1069 class MSCaseInterpolateAtSampleSingleSample : public MSInterpolationCaseBase
1070 {
1071 public:
1072                                         MSCaseInterpolateAtSampleSingleSample   (tcu::TestContext&              testCtx,
1073                                                                                                                          const std::string&             name,
1074                                                                                                                          tcu::UVec3                             imageSize)
1075         : MSInterpolationCaseBase(testCtx, name, ImageMSParams(VK_SAMPLE_COUNT_1_BIT, imageSize)) {}
1076
1077         void                    init                                                                    (void);
1078         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1079         TestInstance*   createInstance                                                  (Context&                               context) const;
1080 };
1081
1082 void MSCaseInterpolateAtSampleSingleSample::init (void)
1083 {
1084         m_testCtx.getLog()
1085                 << tcu::TestLog::Message
1086                 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
1087                 << "    Interpolate varying containing screen space location.\n"
1088                 << "    => fract(screen space location) should be (about) (0.5, 0.5)\n"
1089                 << tcu::TestLog::EndMessage;
1090
1091         MSInterpolationCaseBase::init();
1092 }
1093
1094 void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& programCollection) const
1095 {
1096         // Create vertex shader
1097         std::ostringstream vs;
1098
1099         vs << "#version 440\n"
1100                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1101                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1102                 << "\n"
1103                 << "layout(location = 0) out vec2 vs_out_position_screen;\n"
1104                 << "\n"
1105                 << "out gl_PerVertex {\n"
1106                 << "    vec4  gl_Position;\n"
1107                 << "};\n"
1108                 << "void main (void)\n"
1109                 << "{\n"
1110                 << "    gl_Position                             = vs_in_position_ndc;\n"
1111                 << "    vs_out_position_screen  = vs_in_position_screen;\n"
1112                 << "}\n";
1113
1114         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1115
1116         // Create fragment shader
1117         std::ostringstream fs;
1118
1119         fs << "#version 440\n"
1120                 << "layout(location = 0) in vec2 fs_in_position_screen;\n"
1121                 << "\n"
1122                 << "layout(location = 0) out vec2 fs_out_color;\n"
1123                 << "\n"
1124                 << "void main (void)\n"
1125                 << "{\n"
1126                 << "    const float threshold                                   = 0.15625;\n"
1127                 << "    const vec2  position_screen_at_sample   = interpolateAtSample(fs_in_position_screen, 0);\n"
1128                 << "    const vec2  position_inside_pixel               = fract(position_screen_at_sample);\n"
1129                 << "\n"
1130                 << "    if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
1131                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1132                 << "    else\n"
1133                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1134                 << "}\n";
1135
1136         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1137 }
1138
1139 TestInstance* MSCaseInterpolateAtSampleSingleSample::createInstance (Context& context) const
1140 {
1141         if (!context.getDeviceFeatures().sampleRateShading)
1142                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1143
1144         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1145 }
1146
1147 class MSCaseInterpolateAtSampleIgnoresCentroid : public MSInterpolationCaseBase
1148 {
1149 public:
1150                                         MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext&              testCtx,
1151                                                                                                                          const std::string&             name,
1152                                                                                                                          const ImageMSParams&   imageMSParams)
1153         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1154
1155         void                    init                                                                    (void);
1156         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1157         TestInstance*   createInstance                                                  (Context&                               context) const;
1158 };
1159
1160 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleIgnoresCentroid (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1161 {
1162         return new MSCaseInterpolateAtSampleIgnoresCentroid(testCtx, name, imageMSParams);
1163 }
1164
1165 void MSCaseInterpolateAtSampleIgnoresCentroid::init (void)
1166 {
1167         m_testCtx.getLog()
1168                 << tcu::TestLog::Message
1169                 << "Verifying that interpolateAtSample ignores centroid qualifier.\n"
1170                 << "    Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1171                 << "    => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
1172                 << tcu::TestLog::EndMessage;
1173
1174         MSInterpolationCaseBase::init();
1175 }
1176
1177 void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollections& programCollection) const
1178 {
1179         // Create vertex shader
1180         std::ostringstream vs;
1181
1182         vs << "#version 440\n"
1183                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1184                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1185                 << "\n"
1186                 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1187                 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
1188                 << "\n"
1189                 << "out gl_PerVertex {\n"
1190                 << "    vec4  gl_Position;\n"
1191                 << "};\n"
1192                 << "void main (void)\n"
1193                 << "{\n"
1194                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1195                 << "    vs_out_pos_screen_centroid      = vs_in_position_screen;\n"
1196                 << "    vs_out_pos_screen_fragment      = vs_in_position_screen;\n"
1197                 << "}\n";
1198
1199         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1200
1201         // Create fragment shader
1202         std::ostringstream fs;
1203
1204         fs << "#version 440\n"
1205                 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1206                 << "layout(location = 1)                  in vec2 fs_in_pos_screen_fragment;\n"
1207                 << "\n"
1208                 << "layout(location = 0) out vec2 fs_out_color;\n"
1209                 << "\n"
1210                 << "void main (void)\n"
1211                 << "{\n"
1212                 << "    const float threshold = 0.0005;\n"
1213                 << "\n"
1214                 << "    const vec2 position_a  = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1215                 << "    const vec2 position_b  = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
1216                 << "    const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
1217                 << "\n"
1218                 << "    if (valuesEqual)\n"
1219                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1220                 << "    else\n"
1221                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1222                 << "}\n";
1223
1224         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1225 }
1226
1227 TestInstance* MSCaseInterpolateAtSampleIgnoresCentroid::createInstance (Context& context) const
1228 {
1229         if (!context.getDeviceFeatures().sampleRateShading)
1230                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1231
1232         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1233 }
1234
1235 class MSCaseInterpolateAtSampleConsistency : public MSInterpolationCaseBase
1236 {
1237 public:
1238                                         MSCaseInterpolateAtSampleConsistency    (tcu::TestContext&              testCtx,
1239                                                                                                                          const std::string&             name,
1240                                                                                                                          const ImageMSParams&   imageMSParams)
1241         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1242
1243         void                    init                                                                    (void);
1244         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1245         TestInstance*   createInstance                                                  (Context&                               context) const;
1246 };
1247
1248 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1249 {
1250         return new MSCaseInterpolateAtSampleConsistency(testCtx, name, imageMSParams);
1251 }
1252
1253 void MSCaseInterpolateAtSampleConsistency::init (void)
1254 {
1255         m_testCtx.getLog()
1256                 << tcu::TestLog::Message
1257                 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
1258                 << "    Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1259                 << "    => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
1260                 << tcu::TestLog::EndMessage;
1261
1262         MSInterpolationCaseBase::init();
1263 }
1264
1265 void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& programCollection) const
1266 {
1267         // Create vertex shader
1268         std::ostringstream vs;
1269
1270         vs << "#version 440\n"
1271                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1272                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1273                 << "\n"
1274                 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1275                 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1276                 << "\n"
1277                 << "out gl_PerVertex {\n"
1278                 << "    vec4  gl_Position;\n"
1279                 << "};\n"
1280                 << "void main (void)\n"
1281                 << "{\n"
1282                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1283                 << "    vs_out_pos_screen_centroid      = vs_in_position_screen;\n"
1284                 << "    vs_out_pos_screen_sample        = vs_in_position_screen;\n"
1285                 << "}\n";
1286
1287         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1288
1289         // Create fragment shader
1290         std::ostringstream fs;
1291
1292         fs << "#version 440\n"
1293                 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1294                 << "layout(location = 1) sample   in vec2 fs_in_pos_screen_sample;\n"
1295                 << "\n"
1296                 << "layout(location = 0) out vec2 fs_out_color;\n"
1297                 << "\n"
1298                 << "void main (void)\n"
1299                 << "{\n"
1300                 << "    const float threshold = 0.15625;\n"
1301                 << "\n"
1302                 << "    const vec2  pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1303                 << "    const bool  valuesEqual                            = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"
1304                 << "\n"
1305                 << "    if (valuesEqual)\n"
1306                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1307                 << "    else\n"
1308                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1309                 << "}\n";
1310
1311         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1312 }
1313
1314 TestInstance* MSCaseInterpolateAtSampleConsistency::createInstance (Context& context) const
1315 {
1316         if (!context.getDeviceFeatures().sampleRateShading)
1317                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1318
1319         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1320 }
1321
1322 class MSCaseInterpolateAtCentroidConsistency : public MSInterpolationCaseBase
1323 {
1324 public:
1325                                         MSCaseInterpolateAtCentroidConsistency  (tcu::TestContext&              testCtx,
1326                                                                                                                          const std::string&             name,
1327                                                                                                                          const ImageMSParams&   imageMSParams)
1328         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1329
1330         void                    init                                                                    (void);
1331         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1332         TestInstance*   createInstance                                                  (Context&                               context) const;
1333 };
1334
1335 MSInterpolationCaseBase* createMSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1336 {
1337         return new MSCaseInterpolateAtCentroidConsistency(testCtx, name, imageMSParams);
1338 }
1339
1340 void MSCaseInterpolateAtCentroidConsistency::init (void)
1341 {
1342         m_testCtx.getLog()
1343                 << tcu::TestLog::Message
1344                 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
1345                 << "    Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
1346                 << "    => interpolateAtCentroid(screenSample) = screenCentroid\n"
1347                 << tcu::TestLog::EndMessage;
1348
1349         MSInterpolationCaseBase::init();
1350 }
1351
1352 void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections& programCollection) const
1353 {
1354         // Create vertex shader
1355         std::ostringstream vs;
1356
1357         vs << "#version 440\n"
1358                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1359                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1360                 << "\n"
1361                 << "layout(location = 0) out vec2 vs_out_pos_screen_sample;\n"
1362                 << "layout(location = 1) out vec2 vs_out_pos_screen_centroid;\n"
1363                 << "\n"
1364                 << "out gl_PerVertex {\n"
1365                 << "    vec4  gl_Position;\n"
1366                 << "};\n"
1367                 << "void main (void)\n"
1368                 << "{\n"
1369                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1370                 << "    vs_out_pos_screen_sample        = vs_in_position_screen;\n"
1371                 << "    vs_out_pos_screen_centroid      = vs_in_position_screen;\n"
1372                 << "}\n";
1373
1374         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1375
1376         // Create fragment shader
1377         std::ostringstream fs;
1378
1379         fs << "#version 440\n"
1380                 << "layout(location = 0) sample   in vec2 fs_in_pos_screen_sample;\n"
1381                 << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n"
1382                 << "\n"
1383                 << "layout(location = 0) out vec2 fs_out_color;\n"
1384                 << "\n"
1385                 << "void main (void)\n"
1386                 << "{\n"
1387                 << "    const float threshold = 0.0005;\n"
1388                 << "\n"
1389                 << "    const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample);\n"
1390                 << "    const bool valuesEqual                                  = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n"
1391                 << "\n"
1392                 << "    if (valuesEqual)\n"
1393                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1394                 << "    else\n"
1395                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1396                 << "}\n";
1397
1398         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1399 }
1400
1401 TestInstance* MSCaseInterpolateAtCentroidConsistency::createInstance (Context& context) const
1402 {
1403         if (!context.getDeviceFeatures().sampleRateShading)
1404                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1405
1406         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1407 }
1408
1409 class MSCaseInterpolateAtOffsetPixelCenter : public MSInterpolationCaseBase
1410 {
1411 public:
1412                                         MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext&          testCtx,
1413                                                                                                                  const std::string&             name,
1414                                                                                                                  const ImageMSParams&   imageMSParams)
1415         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1416
1417         void                    init                                                            (void);
1418         void                    initPrograms                                            (vk::SourceCollections& programCollection) const;
1419         TestInstance*   createInstance                                          (Context&                               context) const;
1420 };
1421
1422 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetPixelCenter (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1423 {
1424         return new MSCaseInterpolateAtOffsetPixelCenter(testCtx, name, imageMSParams);
1425 }
1426
1427 void MSCaseInterpolateAtOffsetPixelCenter::init (void)
1428 {
1429         m_testCtx.getLog()
1430                 << tcu::TestLog::Message
1431                 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
1432                 << "    Interpolate varying containing screen space location.\n"
1433                 << "    => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
1434                 << tcu::TestLog::EndMessage;
1435
1436         MSInterpolationCaseBase::init();
1437 }
1438
1439 void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& programCollection) const
1440 {
1441         // Create vertex shader
1442         std::ostringstream vs;
1443
1444         vs << "#version 440\n"
1445                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1446                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1447                 << "\n"
1448                 << "layout(location = 0) out vec2 vs_out_pos_screen;\n"
1449                 << "layout(location = 1) out vec2 vs_out_offset;\n"
1450                 << "\n"
1451                 << "out gl_PerVertex {\n"
1452                 << "    vec4  gl_Position;\n"
1453                 << "};\n"
1454                 << "void main (void)\n"
1455                 << "{\n"
1456                 << "    gl_Position                     = vs_in_position_ndc;\n"
1457                 << "    vs_out_pos_screen       = vs_in_position_screen;\n"
1458                 << "    vs_out_offset           = vs_in_position_ndc.xy * 0.5;\n"
1459                 << "}\n";
1460
1461         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1462
1463         // Create fragment shader
1464         std::ostringstream fs;
1465
1466         fs << "#version 440\n"
1467                 << "layout(location = 0) in  vec2 fs_in_pos_screen;\n"
1468                 << "layout(location = 1) in  vec2 fs_in_offset;\n"
1469                 << "\n"
1470                 << "layout(location = 0) out vec2 fs_out_color;\n"
1471                 << "\n"
1472                 << "void main (void)\n"
1473                 << "{\n"
1474                 << "    const vec2  frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
1475                 << "    const vec2  center_diff = abs(frag_center - fs_in_pos_screen);\n"
1476                 << "    const float threshold   = 0.125;\n"
1477                 << "    bool        valuesEqual = false;\n"
1478                 << "\n"
1479                 << "    if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
1480                 << "        const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
1481                 << "        const vec2 reference_value            = frag_center + fs_in_offset;\n"
1482                 << "\n"
1483                 << "        valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
1484                 << "    }\n"
1485                 << "\n"
1486                 << "    if (valuesEqual)\n"
1487                 << "        fs_out_color = vec2(0.0, 1.0);\n"
1488                 << "    else\n"
1489                 << "        fs_out_color = vec2(1.0, 0.0);\n"
1490                 << "}\n";
1491
1492         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1493 }
1494
1495 TestInstance* MSCaseInterpolateAtOffsetPixelCenter::createInstance (Context& context) const
1496 {
1497         if (!context.getDeviceFeatures().sampleRateShading)
1498                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1499
1500         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1501 }
1502
1503 class MSCaseInterpolateAtOffsetSamplePosition : public MSInterpolationCaseBase
1504 {
1505 public:
1506                                         MSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext&              testCtx,
1507                                                                                                                          const std::string&             name,
1508                                                                                                                          const ImageMSParams&   imageMSParams)
1509         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1510
1511         void                    init                                                                    (void);
1512         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1513         TestInstance*   createInstance                                                  (Context&                               context) const;
1514 };
1515
1516 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1517 {
1518         return new MSCaseInterpolateAtOffsetSamplePosition(testCtx, name, imageMSParams);
1519 }
1520
1521 void MSCaseInterpolateAtOffsetSamplePosition::init (void)
1522 {
1523         m_testCtx.getLog()
1524                 << tcu::TestLog::Message
1525                 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
1526                 << "similar to screen position interpolated at sample.\n"
1527                 << "    Interpolate varying containing screen space location with and without sample qualifier.\n"
1528                 << "    => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
1529                 << tcu::TestLog::EndMessage;
1530
1531         MSInterpolationCaseBase::init();
1532 }
1533
1534 void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollections& programCollection) const
1535 {
1536         // Create vertex shader
1537         std::ostringstream vs;
1538
1539         vs << "#version 440\n"
1540                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1541                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1542                 << "\n"
1543                 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
1544                 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1545                 << "\n"
1546                 << "out gl_PerVertex {\n"
1547                 << "    vec4  gl_Position;\n"
1548                 << "};\n"
1549                 << "void main (void)\n"
1550                 << "{\n"
1551                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1552                 << "    vs_out_pos_screen_fragment      = vs_in_position_screen;\n"
1553                 << "    vs_out_pos_screen_sample        = vs_in_position_screen;\n"
1554                 << "}\n";
1555
1556         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1557
1558         // Create fragment shader
1559         std::ostringstream fs;
1560
1561         fs << "#version 440\n"
1562                 << "layout(location = 0)                in vec2 fs_in_pos_screen_fragment;\n"
1563                 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
1564                 << "\n"
1565                 << "layout(location = 0) out vec2 fs_out_color;\n"
1566                 << "\n"
1567                 << "void main (void)\n"
1568                 << "{\n"
1569                 << "    const float threshold = 0.15625;\n"
1570                 << "\n"
1571                 << "    const vec2 offset                                         = gl_SamplePosition - vec2(0.5, 0.5);\n"
1572                 << "    const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
1573                 << "    const bool valuesEqual                            = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"
1574                 << "\n"
1575                 << "    if (valuesEqual)\n"
1576                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1577                 << "    else\n"
1578                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1579                 << "}\n";
1580
1581         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1582 }
1583
1584 TestInstance* MSCaseInterpolateAtOffsetSamplePosition::createInstance (Context& context) const
1585 {
1586         if (!context.getDeviceFeatures().sampleRateShading)
1587                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1588
1589         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1590 }
1591
1592 class MSInstanceInterpolateBarycentricCoordinates : public MSInterpolationInstanceBase
1593 {
1594 public:
1595                                         MSInstanceInterpolateBarycentricCoordinates     (Context&                               context,
1596                                                                                                                                  const ImageMSParams&   imageMSParams)
1597         : MSInterpolationInstanceBase(context, imageMSParams) {}
1598
1599         VertexDataDesc  getVertexDataDescripton                                         (void) const;
1600         void                    uploadVertexData                                                        (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
1601         tcu::TestStatus verifyResolvedImage                                                     (const tcu::ConstPixelBufferAccess&     imageData) const;
1602
1603 protected:
1604         struct VertexData
1605         {
1606                 VertexData(const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
1607
1608                 tcu::Vec4 positionNdc;
1609                 tcu::Vec3 barycentricCoord;
1610         };
1611 };
1612
1613 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoordinates::getVertexDataDescripton (void) const
1614 {
1615         VertexDataDesc vertexDataDesc;
1616
1617         vertexDataDesc.verticesCount            = 3u;
1618         vertexDataDesc.dataStride                       = sizeof(VertexData);
1619         vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1620         vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1621
1622         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1623         {
1624                 0u,                                                                                     // deUint32     location;
1625                 0u,                                                                                     // deUint32     binding;
1626                 VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
1627                 DE_OFFSET_OF(VertexData, positionNdc),          // deUint32     offset;
1628         };
1629
1630         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1631
1632         const VkVertexInputAttributeDescription vertexAttrBarCoord =
1633         {
1634                 1u,                                                                                     // deUint32     location;
1635                 0u,                                                                                     // deUint32     binding;
1636                 VK_FORMAT_R32G32B32_SFLOAT,                                     // VkFormat     format;
1637                 DE_OFFSET_OF(VertexData, barycentricCoord),     // deUint32     offset;
1638         };
1639
1640         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
1641
1642         return vertexDataDesc;
1643 }
1644
1645 void MSInstanceInterpolateBarycentricCoordinates::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1646 {
1647         // Create buffer storing vertex data
1648         std::vector<VertexData> vertices;
1649
1650         vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
1651         vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
1652         vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
1653
1654         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1655 }
1656
1657 tcu::TestStatus MSInstanceInterpolateBarycentricCoordinates::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1658 {
1659         for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
1660         for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1661         for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
1662         {
1663                 const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1664
1665                 if (firstComponent > 0)
1666                         return tcu::TestStatus::fail("Failed");
1667         }
1668
1669         return tcu::TestStatus::pass("Passed");
1670 }
1671
1672 class MSCaseCentroidQualifierInsidePrimitive : public MSInterpolationCaseBase
1673 {
1674 public:
1675                                         MSCaseCentroidQualifierInsidePrimitive  (tcu::TestContext&              testCtx,
1676                                                                                                                          const std::string&             name,
1677                                                                                                                          const ImageMSParams&   imageMSParams)
1678         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1679
1680         void                    init                                                                    (void);
1681         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1682         TestInstance*   createInstance                                                  (Context&                               context) const;
1683 };
1684
1685 MSInterpolationCaseBase* createMSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1686 {
1687         return new MSCaseCentroidQualifierInsidePrimitive(testCtx, name, imageMSParams);
1688 }
1689
1690 void MSCaseCentroidQualifierInsidePrimitive::init (void)
1691 {
1692         m_testCtx.getLog()
1693                 << tcu::TestLog::Message
1694                 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
1695                 << "    Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
1696                 << "    => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
1697                 << tcu::TestLog::EndMessage;
1698
1699         MSInterpolationCaseBase::init();
1700 }
1701
1702 void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections& programCollection) const
1703 {
1704         // Create vertex shader
1705         std::ostringstream vs;
1706
1707         vs << "#version 440\n"
1708                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1709                 << "layout(location = 1) in vec3 vs_in_barCoord;\n"
1710                 << "\n"
1711                 << "layout(location = 0) out vec3 vs_out_barCoord;\n"
1712                 << "\n"
1713                 << "out gl_PerVertex {\n"
1714                 << "    vec4  gl_Position;\n"
1715                 << "};\n"
1716                 << "void main (void)\n"
1717                 << "{\n"
1718                 << "    gl_Position             = vs_in_position_ndc;\n"
1719                 << "    vs_out_barCoord = vs_in_barCoord;\n"
1720                 << "}\n";
1721
1722         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1723
1724         // Create fragment shader
1725         std::ostringstream fs;
1726
1727         fs << "#version 440\n"
1728                 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
1729                 << "\n"
1730                 << "layout(location = 0) out vec2 fs_out_color;\n"
1731                 << "\n"
1732                 << "void main (void)\n"
1733                 << "{\n"
1734                 << "    if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
1735                 << "                    fs_out_color = vec2(0.0, 1.0);\n"
1736                 << "    else\n"
1737                 << "                    fs_out_color = vec2(1.0, 0.0);\n"
1738                 << "}\n";
1739
1740         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1741 }
1742
1743 TestInstance* MSCaseCentroidQualifierInsidePrimitive::createInstance (Context& context) const
1744 {
1745         return new MSInstanceInterpolateBarycentricCoordinates(context, m_imageMSParams);
1746 }
1747
1748 } // multisample
1749
1750 tcu::TestCaseGroup* makeGroup(  multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr,
1751                                                                 tcu::TestContext&                                               testCtx,
1752                                                                 const std::string                                               groupName,
1753                                                                 const tcu::UVec3                                                imageSizes[],
1754                                                                 const deUint32                                                  imageSizesElemCount,
1755                                                                 const vk::VkSampleCountFlagBits                 imageSamples[],
1756                                                                 const deUint32                                                  imageSamplesElemCount)
1757 {
1758         de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), ""));
1759
1760         for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx)
1761         {
1762                 const tcu::UVec3        imageSize = imageSizes[imageSizeNdx];
1763                 std::ostringstream      imageSizeStream;
1764
1765                 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1766
1767                 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1768
1769                 for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx)
1770                 {
1771                         const vk::VkSampleCountFlagBits         samples                 = imageSamples[imageSamplesNdx];
1772                         const multisample::ImageMSParams        imageMSParams   = multisample::ImageMSParams(samples, imageSize);
1773
1774                         sizeGroup->addChild(createCaseFuncPtr(testCtx, "samples_" + de::toString(samples), imageMSParams));
1775                 }
1776
1777                 caseGroup->addChild(sizeGroup.release());
1778         }
1779         return caseGroup.release();
1780 }
1781
1782 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx)
1783 {
1784         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation"));
1785
1786         const tcu::UVec3 imageSizes[] =
1787         {
1788                 tcu::UVec3(128u, 128u, 1u),
1789                 tcu::UVec3(137u, 191u, 1u),
1790         };
1791
1792         const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1793
1794         const vk::VkSampleCountFlagBits imageSamples[] =
1795         {
1796                 vk::VK_SAMPLE_COUNT_2_BIT,
1797                 vk::VK_SAMPLE_COUNT_4_BIT,
1798                 vk::VK_SAMPLE_COUNT_8_BIT,
1799                 vk::VK_SAMPLE_COUNT_16_BIT,
1800                 vk::VK_SAMPLE_COUNT_32_BIT,
1801                 vk::VK_SAMPLE_COUNT_64_BIT,
1802         };
1803
1804         const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1805
1806         de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample_", ""));
1807
1808         for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1809         {
1810                 const tcu::UVec3        imageSize = imageSizes[imageSizeNdx];
1811                 std::ostringstream      imageSizeStream;
1812
1813                 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1814
1815                 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1816
1817                 sizeGroup->addChild(new multisample::MSCaseInterpolateAtSampleSingleSample(testCtx, "samples_" + de::toString(1), imageSize));
1818
1819                 caseGroup->addChild(sizeGroup.release());
1820         }
1821
1822         testGroup->addChild(caseGroup.release());
1823
1824         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleDistinctValues,       testCtx, "sample_interpolate_at_distinct_values",       imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1825         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleIgnoresCentroid,      testCtx, "sample_interpolate_at_ignores_centroid",      imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1826         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleConsistency,          testCtx, "sample_interpolate_at_consistency",           imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1827         testGroup->addChild(makeGroup(multisample::createMSCaseSampleQualifierDistinctValues,           testCtx, "sample_qualifier_distinct_values",            imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1828         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtCentroidConsistency,        testCtx, "centroid_interpolate_at_consistency",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1829         testGroup->addChild(makeGroup(multisample::createMSCaseCentroidQualifierInsidePrimitive,        testCtx, "centroid_qualifier_inside_primitive",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1830         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetPixelCenter,          testCtx, "offset_interpolate_at_pixel_center",          imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1831         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetSamplePosition,       testCtx, "offset_interpolate_at_sample_position",       imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1832
1833         return testGroup.release();
1834 }
1835
1836 } // pipeline
1837 } // vkt