46f94b5aeeea8ebe4aef215d31cac0e438e7a555
[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         return new MSInstanceDistinctValues(context, m_imageMSParams);
903 }
904
905 class MSCaseInterpolateAtSampleDistinctValues : public MSInterpolationCaseBase
906 {
907 public:
908                                         MSCaseInterpolateAtSampleDistinctValues (tcu::TestContext&              testCtx,
909                                                                                                                          const std::string&             name,
910                                                                                                                          const ImageMSParams&   imageMSParams)
911         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
912
913         void                    init                                                                    (void);
914         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
915         TestInstance*   createInstance                                                  (Context&                               context) const;
916 };
917
918 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
919 {
920         return new MSCaseInterpolateAtSampleDistinctValues(testCtx, name, imageMSParams);
921 }
922
923 void MSCaseInterpolateAtSampleDistinctValues::init (void)
924 {
925         m_testCtx.getLog()
926                 << tcu::TestLog::Message
927                 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
928                 << "    Render full screen traingle with quadratic function defining red/green color pattern division.\n"
929                 << "    => Resulting image should contain n+1 different colors, where n = sample count.\n"
930                 << tcu::TestLog::EndMessage;
931
932         MSInterpolationCaseBase::init();
933 }
934
935 void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
936 {
937         // Create vertex shader
938         std::ostringstream vs;
939
940         vs << "#version 440\n"
941                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
942                 << "\n"
943                 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
944                 << "\n"
945                 << "out gl_PerVertex {\n"
946                 << "    vec4  gl_Position;\n"
947                 << "};\n"
948                 << "void main (void)\n"
949                 << "{\n"
950                 << "    gl_Position                     = vs_in_position_ndc;\n"
951                 << "    vs_out_position_ndc = vs_in_position_ndc;\n"
952                 << "}\n";
953
954         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
955
956         // Create fragment shader
957         std::ostringstream fs;
958
959         fs << "#version 440\n"
960                 << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
961                 << "\n"
962                 << "layout(location = 0) out vec2 fs_out_color;\n"
963                 << "\n"
964                 << "void main (void)\n"
965                 << "{\n"
966                 << "    const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
967                 << "    if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
968                 << "            fs_out_color = vec2(0.0, 1.0);\n"
969                 << "    else\n"
970                 << "            fs_out_color = vec2(1.0, 0.0);\n"
971                 << "}\n";
972
973         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
974 }
975
976 TestInstance* MSCaseInterpolateAtSampleDistinctValues::createInstance (Context& context) const
977 {
978         if (!context.getDeviceFeatures().sampleRateShading)
979                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
980
981         return new MSInstanceDistinctValues(context, m_imageMSParams);
982 }
983
984 class MSInstanceInterpolateScreenPosition : public MSInterpolationInstanceBase
985 {
986 public:
987                                         MSInstanceInterpolateScreenPosition     (Context&                               context,
988                                                                                                                  const ImageMSParams&   imageMSParams)
989         : MSInterpolationInstanceBase(context, imageMSParams) {}
990
991         VertexDataDesc  getVertexDataDescripton                         (void) const;
992         void                    uploadVertexData                                        (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
993         tcu::TestStatus verifyResolvedImage                                     (const tcu::ConstPixelBufferAccess&     imageData) const;
994
995 protected:
996         struct VertexData
997         {
998                 VertexData(const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
999
1000                 tcu::Vec4 positionNdc;
1001                 tcu::Vec2 positionScreen;
1002         };
1003 };
1004
1005 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition::getVertexDataDescripton (void) const
1006 {
1007         VertexDataDesc vertexDataDesc;
1008
1009         vertexDataDesc.verticesCount            = 4u;
1010         vertexDataDesc.dataStride                       = sizeof(VertexData);
1011         vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1012         vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1013
1014         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1015         {
1016                 0u,                                                                                     // deUint32     location;
1017                 0u,                                                                                     // deUint32     binding;
1018                 VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
1019                 DE_OFFSET_OF(VertexData, positionNdc),          // deUint32     offset;
1020         };
1021
1022         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1023
1024         const VkVertexInputAttributeDescription vertexAttribPositionScreen =
1025         {
1026                 1u,                                                                                     // deUint32     location;
1027                 0u,                                                                                     // deUint32     binding;
1028                 VK_FORMAT_R32G32_SFLOAT,                                        // VkFormat     format;
1029                 DE_OFFSET_OF(VertexData, positionScreen),       // deUint32     offset;
1030         };
1031
1032         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
1033
1034         return vertexDataDesc;
1035 }
1036
1037 void MSInstanceInterpolateScreenPosition::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1038 {
1039         const tcu::UVec3 layerSize              = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
1040         const float              screenSizeX    = static_cast<float>(layerSize.x());
1041         const float              screenSizeY    = static_cast<float>(layerSize.y());
1042
1043         std::vector<VertexData> vertices;
1044
1045         vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,                0.0f)));
1046         vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
1047         vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,                screenSizeY)));
1048         vertices.push_back(VertexData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
1049
1050         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1051 }
1052
1053 tcu::TestStatus MSInstanceInterpolateScreenPosition::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1054 {
1055         for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
1056         for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1057         for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
1058         {
1059                 const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1060
1061                 if (firstComponent > 0)
1062                         return tcu::TestStatus::fail("Failed");
1063         }
1064         return tcu::TestStatus::pass("Passed");
1065 }
1066
1067 class MSCaseInterpolateAtSampleSingleSample : public MSInterpolationCaseBase
1068 {
1069 public:
1070                                         MSCaseInterpolateAtSampleSingleSample   (tcu::TestContext&              testCtx,
1071                                                                                                                          const std::string&             name,
1072                                                                                                                          tcu::UVec3                             imageSize)
1073         : MSInterpolationCaseBase(testCtx, name, ImageMSParams(VK_SAMPLE_COUNT_1_BIT, imageSize)) {}
1074
1075         void                    init                                                                    (void);
1076         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1077         TestInstance*   createInstance                                                  (Context&                               context) const;
1078 };
1079
1080 void MSCaseInterpolateAtSampleSingleSample::init (void)
1081 {
1082         m_testCtx.getLog()
1083                 << tcu::TestLog::Message
1084                 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
1085                 << "    Interpolate varying containing screen space location.\n"
1086                 << "    => fract(screen space location) should be (about) (0.5, 0.5)\n"
1087                 << tcu::TestLog::EndMessage;
1088
1089         MSInterpolationCaseBase::init();
1090 }
1091
1092 void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& programCollection) const
1093 {
1094         // Create vertex shader
1095         std::ostringstream vs;
1096
1097         vs << "#version 440\n"
1098                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1099                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1100                 << "\n"
1101                 << "layout(location = 0) out vec2 vs_out_position_screen;\n"
1102                 << "\n"
1103                 << "out gl_PerVertex {\n"
1104                 << "    vec4  gl_Position;\n"
1105                 << "};\n"
1106                 << "void main (void)\n"
1107                 << "{\n"
1108                 << "    gl_Position                             = vs_in_position_ndc;\n"
1109                 << "    vs_out_position_screen  = vs_in_position_screen;\n"
1110                 << "}\n";
1111
1112         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1113
1114         // Create fragment shader
1115         std::ostringstream fs;
1116
1117         fs << "#version 440\n"
1118                 << "layout(location = 0) in vec2 fs_in_position_screen;\n"
1119                 << "\n"
1120                 << "layout(location = 0) out vec2 fs_out_color;\n"
1121                 << "\n"
1122                 << "void main (void)\n"
1123                 << "{\n"
1124                 << "    const float threshold                                   = 0.15625;\n"
1125                 << "    const vec2  position_screen_at_sample   = interpolateAtSample(fs_in_position_screen, 0);\n"
1126                 << "    const vec2  position_inside_pixel               = fract(position_screen_at_sample);\n"
1127                 << "\n"
1128                 << "    if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
1129                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1130                 << "    else\n"
1131                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1132                 << "}\n";
1133
1134         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1135 }
1136
1137 TestInstance* MSCaseInterpolateAtSampleSingleSample::createInstance (Context& context) const
1138 {
1139         if (!context.getDeviceFeatures().sampleRateShading)
1140                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1141
1142         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1143 }
1144
1145 class MSCaseInterpolateAtSampleIgnoresCentroid : public MSInterpolationCaseBase
1146 {
1147 public:
1148                                         MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext&              testCtx,
1149                                                                                                                          const std::string&             name,
1150                                                                                                                          const ImageMSParams&   imageMSParams)
1151         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1152
1153         void                    init                                                                    (void);
1154         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1155         TestInstance*   createInstance                                                  (Context&                               context) const;
1156 };
1157
1158 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleIgnoresCentroid (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1159 {
1160         return new MSCaseInterpolateAtSampleIgnoresCentroid(testCtx, name, imageMSParams);
1161 }
1162
1163 void MSCaseInterpolateAtSampleIgnoresCentroid::init (void)
1164 {
1165         m_testCtx.getLog()
1166                 << tcu::TestLog::Message
1167                 << "Verifying that interpolateAtSample ignores centroid qualifier.\n"
1168                 << "    Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1169                 << "    => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
1170                 << tcu::TestLog::EndMessage;
1171
1172         MSInterpolationCaseBase::init();
1173 }
1174
1175 void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollections& programCollection) const
1176 {
1177         // Create vertex shader
1178         std::ostringstream vs;
1179
1180         vs << "#version 440\n"
1181                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1182                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1183                 << "\n"
1184                 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1185                 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
1186                 << "\n"
1187                 << "out gl_PerVertex {\n"
1188                 << "    vec4  gl_Position;\n"
1189                 << "};\n"
1190                 << "void main (void)\n"
1191                 << "{\n"
1192                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1193                 << "    vs_out_pos_screen_centroid      = vs_in_position_screen;\n"
1194                 << "    vs_out_pos_screen_fragment      = vs_in_position_screen;\n"
1195                 << "}\n";
1196
1197         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1198
1199         // Create fragment shader
1200         std::ostringstream fs;
1201
1202         fs << "#version 440\n"
1203                 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1204                 << "layout(location = 1)                  in vec2 fs_in_pos_screen_fragment;\n"
1205                 << "\n"
1206                 << "layout(location = 0) out vec2 fs_out_color;\n"
1207                 << "\n"
1208                 << "void main (void)\n"
1209                 << "{\n"
1210                 << "    const float threshold = 0.0005;\n"
1211                 << "\n"
1212                 << "    const vec2 position_a  = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1213                 << "    const vec2 position_b  = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
1214                 << "    const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
1215                 << "\n"
1216                 << "    if (valuesEqual)\n"
1217                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1218                 << "    else\n"
1219                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1220                 << "}\n";
1221
1222         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1223 }
1224
1225 TestInstance* MSCaseInterpolateAtSampleIgnoresCentroid::createInstance (Context& context) const
1226 {
1227         if (!context.getDeviceFeatures().sampleRateShading)
1228                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1229
1230         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1231 }
1232
1233 class MSCaseInterpolateAtSampleConsistency : public MSInterpolationCaseBase
1234 {
1235 public:
1236                                         MSCaseInterpolateAtSampleConsistency    (tcu::TestContext&              testCtx,
1237                                                                                                                          const std::string&             name,
1238                                                                                                                          const ImageMSParams&   imageMSParams)
1239         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1240
1241         void                    init                                                                    (void);
1242         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1243         TestInstance*   createInstance                                                  (Context&                               context) const;
1244 };
1245
1246 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1247 {
1248         return new MSCaseInterpolateAtSampleConsistency(testCtx, name, imageMSParams);
1249 }
1250
1251 void MSCaseInterpolateAtSampleConsistency::init (void)
1252 {
1253         m_testCtx.getLog()
1254                 << tcu::TestLog::Message
1255                 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
1256                 << "    Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1257                 << "    => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
1258                 << tcu::TestLog::EndMessage;
1259
1260         MSInterpolationCaseBase::init();
1261 }
1262
1263 void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& programCollection) const
1264 {
1265         // Create vertex shader
1266         std::ostringstream vs;
1267
1268         vs << "#version 440\n"
1269                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1270                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1271                 << "\n"
1272                 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1273                 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1274                 << "\n"
1275                 << "out gl_PerVertex {\n"
1276                 << "    vec4  gl_Position;\n"
1277                 << "};\n"
1278                 << "void main (void)\n"
1279                 << "{\n"
1280                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1281                 << "    vs_out_pos_screen_centroid      = vs_in_position_screen;\n"
1282                 << "    vs_out_pos_screen_sample        = vs_in_position_screen;\n"
1283                 << "}\n";
1284
1285         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1286
1287         // Create fragment shader
1288         std::ostringstream fs;
1289
1290         fs << "#version 440\n"
1291                 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1292                 << "layout(location = 1) sample   in vec2 fs_in_pos_screen_sample;\n"
1293                 << "\n"
1294                 << "layout(location = 0) out vec2 fs_out_color;\n"
1295                 << "\n"
1296                 << "void main (void)\n"
1297                 << "{\n"
1298                 << "    const float threshold = 0.15625;\n"
1299                 << "\n"
1300                 << "    const vec2  pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1301                 << "    const bool  valuesEqual                            = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"
1302                 << "\n"
1303                 << "    if (valuesEqual)\n"
1304                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1305                 << "    else\n"
1306                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1307                 << "}\n";
1308
1309         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1310 }
1311
1312 TestInstance* MSCaseInterpolateAtSampleConsistency::createInstance (Context& context) const
1313 {
1314         if (!context.getDeviceFeatures().sampleRateShading)
1315                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1316
1317         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1318 }
1319
1320 class MSCaseInterpolateAtCentroidConsistency : public MSInterpolationCaseBase
1321 {
1322 public:
1323                                         MSCaseInterpolateAtCentroidConsistency  (tcu::TestContext&              testCtx,
1324                                                                                                                          const std::string&             name,
1325                                                                                                                          const ImageMSParams&   imageMSParams)
1326         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1327
1328         void                    init                                                                    (void);
1329         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1330         TestInstance*   createInstance                                                  (Context&                               context) const;
1331 };
1332
1333 MSInterpolationCaseBase* createMSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1334 {
1335         return new MSCaseInterpolateAtCentroidConsistency(testCtx, name, imageMSParams);
1336 }
1337
1338 void MSCaseInterpolateAtCentroidConsistency::init (void)
1339 {
1340         m_testCtx.getLog()
1341                 << tcu::TestLog::Message
1342                 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
1343                 << "    Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
1344                 << "    => interpolateAtCentroid(screenSample) = screenCentroid\n"
1345                 << tcu::TestLog::EndMessage;
1346
1347         MSInterpolationCaseBase::init();
1348 }
1349
1350 void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections& programCollection) const
1351 {
1352         // Create vertex shader
1353         std::ostringstream vs;
1354
1355         vs << "#version 440\n"
1356                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1357                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1358                 << "\n"
1359                 << "layout(location = 0) out vec2 vs_out_pos_screen_sample;\n"
1360                 << "layout(location = 1) out vec2 vs_out_pos_screen_centroid;\n"
1361                 << "\n"
1362                 << "out gl_PerVertex {\n"
1363                 << "    vec4  gl_Position;\n"
1364                 << "};\n"
1365                 << "void main (void)\n"
1366                 << "{\n"
1367                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1368                 << "    vs_out_pos_screen_sample        = vs_in_position_screen;\n"
1369                 << "    vs_out_pos_screen_centroid      = vs_in_position_screen;\n"
1370                 << "}\n";
1371
1372         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1373
1374         // Create fragment shader
1375         std::ostringstream fs;
1376
1377         fs << "#version 440\n"
1378                 << "layout(location = 0) sample   in vec2 fs_in_pos_screen_sample;\n"
1379                 << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n"
1380                 << "\n"
1381                 << "layout(location = 0) out vec2 fs_out_color;\n"
1382                 << "\n"
1383                 << "void main (void)\n"
1384                 << "{\n"
1385                 << "    const float threshold = 0.0005;\n"
1386                 << "\n"
1387                 << "    const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample);\n"
1388                 << "    const bool valuesEqual                                  = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n"
1389                 << "\n"
1390                 << "    if (valuesEqual)\n"
1391                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1392                 << "    else\n"
1393                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1394                 << "}\n";
1395
1396         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1397 }
1398
1399 TestInstance* MSCaseInterpolateAtCentroidConsistency::createInstance (Context& context) const
1400 {
1401         if (!context.getDeviceFeatures().sampleRateShading)
1402                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1403
1404         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1405 }
1406
1407 class MSCaseInterpolateAtOffsetPixelCenter : public MSInterpolationCaseBase
1408 {
1409 public:
1410                                         MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext&          testCtx,
1411                                                                                                                  const std::string&             name,
1412                                                                                                                  const ImageMSParams&   imageMSParams)
1413         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1414
1415         void                    init                                                            (void);
1416         void                    initPrograms                                            (vk::SourceCollections& programCollection) const;
1417         TestInstance*   createInstance                                          (Context&                               context) const;
1418 };
1419
1420 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetPixelCenter (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1421 {
1422         return new MSCaseInterpolateAtOffsetPixelCenter(testCtx, name, imageMSParams);
1423 }
1424
1425 void MSCaseInterpolateAtOffsetPixelCenter::init (void)
1426 {
1427         m_testCtx.getLog()
1428                 << tcu::TestLog::Message
1429                 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
1430                 << "    Interpolate varying containing screen space location.\n"
1431                 << "    => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
1432                 << tcu::TestLog::EndMessage;
1433
1434         MSInterpolationCaseBase::init();
1435 }
1436
1437 void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& programCollection) const
1438 {
1439         // Create vertex shader
1440         std::ostringstream vs;
1441
1442         vs << "#version 440\n"
1443                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1444                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1445                 << "\n"
1446                 << "layout(location = 0) out vec2 vs_out_pos_screen;\n"
1447                 << "layout(location = 1) out vec2 vs_out_offset;\n"
1448                 << "\n"
1449                 << "out gl_PerVertex {\n"
1450                 << "    vec4  gl_Position;\n"
1451                 << "};\n"
1452                 << "void main (void)\n"
1453                 << "{\n"
1454                 << "    gl_Position                     = vs_in_position_ndc;\n"
1455                 << "    vs_out_pos_screen       = vs_in_position_screen;\n"
1456                 << "    vs_out_offset           = vs_in_position_ndc.xy * 0.5;\n"
1457                 << "}\n";
1458
1459         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1460
1461         // Create fragment shader
1462         std::ostringstream fs;
1463
1464         fs << "#version 440\n"
1465                 << "layout(location = 0) in  vec2 fs_in_pos_screen;\n"
1466                 << "layout(location = 1) in  vec2 fs_in_offset;\n"
1467                 << "\n"
1468                 << "layout(location = 0) out vec2 fs_out_color;\n"
1469                 << "\n"
1470                 << "void main (void)\n"
1471                 << "{\n"
1472                 << "    const vec2  frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
1473                 << "    const vec2  center_diff = abs(frag_center - fs_in_pos_screen);\n"
1474                 << "    const float threshold   = 0.125;\n"
1475                 << "    bool        valuesEqual = false;\n"
1476                 << "\n"
1477                 << "    if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
1478                 << "        const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
1479                 << "        const vec2 reference_value            = frag_center + fs_in_offset;\n"
1480                 << "\n"
1481                 << "        valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
1482                 << "    }\n"
1483                 << "\n"
1484                 << "    if (valuesEqual)\n"
1485                 << "        fs_out_color = vec2(0.0, 1.0);\n"
1486                 << "    else\n"
1487                 << "        fs_out_color = vec2(1.0, 0.0);\n"
1488                 << "}\n";
1489
1490         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1491 }
1492
1493 TestInstance* MSCaseInterpolateAtOffsetPixelCenter::createInstance (Context& context) const
1494 {
1495         if (!context.getDeviceFeatures().sampleRateShading)
1496                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1497
1498         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1499 }
1500
1501 class MSCaseInterpolateAtOffsetSamplePosition : public MSInterpolationCaseBase
1502 {
1503 public:
1504                                         MSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext&              testCtx,
1505                                                                                                                          const std::string&             name,
1506                                                                                                                          const ImageMSParams&   imageMSParams)
1507         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1508
1509         void                    init                                                                    (void);
1510         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1511         TestInstance*   createInstance                                                  (Context&                               context) const;
1512 };
1513
1514 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1515 {
1516         return new MSCaseInterpolateAtOffsetSamplePosition(testCtx, name, imageMSParams);
1517 }
1518
1519 void MSCaseInterpolateAtOffsetSamplePosition::init (void)
1520 {
1521         m_testCtx.getLog()
1522                 << tcu::TestLog::Message
1523                 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
1524                 << "similar to screen position interpolated at sample.\n"
1525                 << "    Interpolate varying containing screen space location with and without sample qualifier.\n"
1526                 << "    => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
1527                 << tcu::TestLog::EndMessage;
1528
1529         MSInterpolationCaseBase::init();
1530 }
1531
1532 void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollections& programCollection) const
1533 {
1534         // Create vertex shader
1535         std::ostringstream vs;
1536
1537         vs << "#version 440\n"
1538                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1539                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1540                 << "\n"
1541                 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
1542                 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1543                 << "\n"
1544                 << "out gl_PerVertex {\n"
1545                 << "    vec4  gl_Position;\n"
1546                 << "};\n"
1547                 << "void main (void)\n"
1548                 << "{\n"
1549                 << "    gl_Position                                     = vs_in_position_ndc;\n"
1550                 << "    vs_out_pos_screen_fragment      = vs_in_position_screen;\n"
1551                 << "    vs_out_pos_screen_sample        = vs_in_position_screen;\n"
1552                 << "}\n";
1553
1554         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1555
1556         // Create fragment shader
1557         std::ostringstream fs;
1558
1559         fs << "#version 440\n"
1560                 << "layout(location = 0)                in vec2 fs_in_pos_screen_fragment;\n"
1561                 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
1562                 << "\n"
1563                 << "layout(location = 0) out vec2 fs_out_color;\n"
1564                 << "\n"
1565                 << "void main (void)\n"
1566                 << "{\n"
1567                 << "    const float threshold = 0.15625;\n"
1568                 << "\n"
1569                 << "    const vec2 offset                                         = gl_SamplePosition - vec2(0.5, 0.5);\n"
1570                 << "    const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
1571                 << "    const bool valuesEqual                            = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"
1572                 << "\n"
1573                 << "    if (valuesEqual)\n"
1574                 << "            fs_out_color = vec2(0.0, 1.0);\n"
1575                 << "    else\n"
1576                 << "            fs_out_color = vec2(1.0, 0.0);\n"
1577                 << "}\n";
1578
1579         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1580 }
1581
1582 TestInstance* MSCaseInterpolateAtOffsetSamplePosition::createInstance (Context& context) const
1583 {
1584         if (!context.getDeviceFeatures().sampleRateShading)
1585                 TCU_THROW(NotSupportedError, "sampleRateShading support required");
1586
1587         return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1588 }
1589
1590 class MSInstanceInterpolateBarycentricCoordinates : public MSInterpolationInstanceBase
1591 {
1592 public:
1593                                         MSInstanceInterpolateBarycentricCoordinates     (Context&                               context,
1594                                                                                                                                  const ImageMSParams&   imageMSParams)
1595         : MSInterpolationInstanceBase(context, imageMSParams) {}
1596
1597         VertexDataDesc  getVertexDataDescripton                                         (void) const;
1598         void                    uploadVertexData                                                        (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
1599         tcu::TestStatus verifyResolvedImage                                                     (const tcu::ConstPixelBufferAccess&     imageData) const;
1600
1601 protected:
1602         struct VertexData
1603         {
1604                 VertexData(const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
1605
1606                 tcu::Vec4 positionNdc;
1607                 tcu::Vec3 barycentricCoord;
1608         };
1609 };
1610
1611 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoordinates::getVertexDataDescripton (void) const
1612 {
1613         VertexDataDesc vertexDataDesc;
1614
1615         vertexDataDesc.verticesCount            = 3u;
1616         vertexDataDesc.dataStride                       = sizeof(VertexData);
1617         vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1618         vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1619
1620         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1621         {
1622                 0u,                                                                                     // deUint32     location;
1623                 0u,                                                                                     // deUint32     binding;
1624                 VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
1625                 DE_OFFSET_OF(VertexData, positionNdc),          // deUint32     offset;
1626         };
1627
1628         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1629
1630         const VkVertexInputAttributeDescription vertexAttrBarCoord =
1631         {
1632                 1u,                                                                                     // deUint32     location;
1633                 0u,                                                                                     // deUint32     binding;
1634                 VK_FORMAT_R32G32B32_SFLOAT,                                     // VkFormat     format;
1635                 DE_OFFSET_OF(VertexData, barycentricCoord),     // deUint32     offset;
1636         };
1637
1638         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
1639
1640         return vertexDataDesc;
1641 }
1642
1643 void MSInstanceInterpolateBarycentricCoordinates::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1644 {
1645         // Create buffer storing vertex data
1646         std::vector<VertexData> vertices;
1647
1648         vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
1649         vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
1650         vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
1651
1652         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1653 }
1654
1655 tcu::TestStatus MSInstanceInterpolateBarycentricCoordinates::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1656 {
1657         for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
1658         for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1659         for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
1660         {
1661                 const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1662
1663                 if (firstComponent > 0)
1664                         return tcu::TestStatus::fail("Failed");
1665         }
1666
1667         return tcu::TestStatus::pass("Passed");
1668 }
1669
1670 class MSCaseCentroidQualifierInsidePrimitive : public MSInterpolationCaseBase
1671 {
1672 public:
1673                                         MSCaseCentroidQualifierInsidePrimitive  (tcu::TestContext&              testCtx,
1674                                                                                                                          const std::string&             name,
1675                                                                                                                          const ImageMSParams&   imageMSParams)
1676         : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1677
1678         void                    init                                                                    (void);
1679         void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
1680         TestInstance*   createInstance                                                  (Context&                               context) const;
1681 };
1682
1683 MSInterpolationCaseBase* createMSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1684 {
1685         return new MSCaseCentroidQualifierInsidePrimitive(testCtx, name, imageMSParams);
1686 }
1687
1688 void MSCaseCentroidQualifierInsidePrimitive::init (void)
1689 {
1690         m_testCtx.getLog()
1691                 << tcu::TestLog::Message
1692                 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
1693                 << "    Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
1694                 << "    => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
1695                 << tcu::TestLog::EndMessage;
1696
1697         MSInterpolationCaseBase::init();
1698 }
1699
1700 void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections& programCollection) const
1701 {
1702         // Create vertex shader
1703         std::ostringstream vs;
1704
1705         vs << "#version 440\n"
1706                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1707                 << "layout(location = 1) in vec3 vs_in_barCoord;\n"
1708                 << "\n"
1709                 << "layout(location = 0) out vec3 vs_out_barCoord;\n"
1710                 << "\n"
1711                 << "out gl_PerVertex {\n"
1712                 << "    vec4  gl_Position;\n"
1713                 << "};\n"
1714                 << "void main (void)\n"
1715                 << "{\n"
1716                 << "    gl_Position             = vs_in_position_ndc;\n"
1717                 << "    vs_out_barCoord = vs_in_barCoord;\n"
1718                 << "}\n";
1719
1720         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1721
1722         // Create fragment shader
1723         std::ostringstream fs;
1724
1725         fs << "#version 440\n"
1726                 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
1727                 << "\n"
1728                 << "layout(location = 0) out vec2 fs_out_color;\n"
1729                 << "\n"
1730                 << "void main (void)\n"
1731                 << "{\n"
1732                 << "    if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
1733                 << "                    fs_out_color = vec2(0.0, 1.0);\n"
1734                 << "    else\n"
1735                 << "                    fs_out_color = vec2(1.0, 0.0);\n"
1736                 << "}\n";
1737
1738         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1739 }
1740
1741 TestInstance* MSCaseCentroidQualifierInsidePrimitive::createInstance (Context& context) const
1742 {
1743         return new MSInstanceInterpolateBarycentricCoordinates(context, m_imageMSParams);
1744 }
1745
1746 } // multisample
1747
1748 tcu::TestCaseGroup* makeGroup(  multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr,
1749                                                                 tcu::TestContext&                                               testCtx,
1750                                                                 const std::string                                               groupName,
1751                                                                 const tcu::UVec3                                                imageSizes[],
1752                                                                 const deUint32                                                  imageSizesElemCount,
1753                                                                 const vk::VkSampleCountFlagBits                 imageSamples[],
1754                                                                 const deUint32                                                  imageSamplesElemCount)
1755 {
1756         de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), ""));
1757
1758         for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx)
1759         {
1760                 const tcu::UVec3        imageSize = imageSizes[imageSizeNdx];
1761                 std::ostringstream      imageSizeStream;
1762
1763                 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1764
1765                 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1766
1767                 for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx)
1768                 {
1769                         const vk::VkSampleCountFlagBits         samples                 = imageSamples[imageSamplesNdx];
1770                         const multisample::ImageMSParams        imageMSParams   = multisample::ImageMSParams(samples, imageSize);
1771
1772                         sizeGroup->addChild(createCaseFuncPtr(testCtx, "samples_" + de::toString(samples), imageMSParams));
1773                 }
1774
1775                 caseGroup->addChild(sizeGroup.release());
1776         }
1777         return caseGroup.release();
1778 }
1779
1780 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx)
1781 {
1782         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation"));
1783
1784         const tcu::UVec3 imageSizes[] =
1785         {
1786                 tcu::UVec3(128u, 128u, 1u),
1787                 tcu::UVec3(137u, 191u, 1u),
1788         };
1789
1790         const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1791
1792         const vk::VkSampleCountFlagBits imageSamples[] =
1793         {
1794                 vk::VK_SAMPLE_COUNT_2_BIT,
1795                 vk::VK_SAMPLE_COUNT_4_BIT,
1796                 vk::VK_SAMPLE_COUNT_8_BIT,
1797                 vk::VK_SAMPLE_COUNT_16_BIT,
1798                 vk::VK_SAMPLE_COUNT_32_BIT,
1799                 vk::VK_SAMPLE_COUNT_64_BIT,
1800         };
1801
1802         const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1803
1804         de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample_", ""));
1805
1806         for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1807         {
1808                 const tcu::UVec3        imageSize = imageSizes[imageSizeNdx];
1809                 std::ostringstream      imageSizeStream;
1810
1811                 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1812
1813                 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1814
1815                 sizeGroup->addChild(new multisample::MSCaseInterpolateAtSampleSingleSample(testCtx, "samples_" + de::toString(1), imageSize));
1816
1817                 caseGroup->addChild(sizeGroup.release());
1818         }
1819
1820         testGroup->addChild(caseGroup.release());
1821
1822         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleDistinctValues,       testCtx, "sample_interpolate_at_distinct_values",       imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1823         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleIgnoresCentroid,      testCtx, "sample_interpolate_at_ignores_centroid",      imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1824         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleConsistency,          testCtx, "sample_interpolate_at_consistency",           imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1825         testGroup->addChild(makeGroup(multisample::createMSCaseSampleQualifierDistinctValues,           testCtx, "sample_qualifier_distinct_values",            imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1826         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtCentroidConsistency,        testCtx, "centroid_interpolate_at_consistency",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1827         testGroup->addChild(makeGroup(multisample::createMSCaseCentroidQualifierInsidePrimitive,        testCtx, "centroid_qualifier_inside_primitive",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1828         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetPixelCenter,          testCtx, "offset_interpolate_at_pixel_center",          imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1829         testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetSamplePosition,       testCtx, "offset_interpolate_at_sample_position",       imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1830
1831         return testGroup.release();
1832 }
1833
1834 } // pipeline
1835 } // vkt