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