InterpolateAt{Offset, Sample} with linear interpolation tests
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawMultisampleLinearInterpolationTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file vktDrawMultisampleLinearInterpolationTests.cpp
22  * \brief InterpolateAt tests with linear interpolation
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawMultisampleLinearInterpolationTests.hpp"
26
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 namespace vkt
34 {
35 namespace Draw
36 {
37 namespace
38 {
39 using namespace vk;
40
41 class MultisampleLinearInterpolationTestInstance : public TestInstance
42 {
43 public:
44                                                 MultisampleLinearInterpolationTestInstance      (Context&                                               context,
45                                                                                                                                          const tcu::IVec2                               renderSize,
46                                                                                                                                          const float                                    interpolationRange,
47                                                                                                                                          const VkSampleCountFlagBits    sampleCountFlagBits,
48                                                                                                                                          const bool                                             useDynamicRendering)
49                                                 : vkt::TestInstance             (context)
50                                                 , m_renderSize                  (renderSize)
51                                                 , m_interpolationRange  (interpolationRange)
52                                                 , m_sampleCountFlagBits (sampleCountFlagBits)
53                                                 , m_useDynamicRendering (useDynamicRendering)
54                                                 {}
55
56                                                 ~MultisampleLinearInterpolationTestInstance     (void)
57                                                 {}
58
59         tcu::TestStatus         iterate                                                                         (void);
60
61 private:
62         const tcu::IVec2                        m_renderSize;
63         const float                                     m_interpolationRange;
64         const VkSampleCountFlagBits     m_sampleCountFlagBits;
65         const bool                                      m_useDynamicRendering;
66 };
67
68 tcu::TestStatus MultisampleLinearInterpolationTestInstance::iterate (void)
69 {
70         const DeviceInterface&                                          vk                                      = m_context.getDeviceInterface();
71         const VkDevice                                                          device                          = m_context.getDevice();
72
73         tcu::ConstPixelBufferAccess                                     resultPixelBufferAccesses[2];
74         de::SharedPtr<Image>                                            colorTargetImages[2];
75         de::SharedPtr<Image>                                            multisampleImages[2];
76
77         const VkFormat                                                          imageColorFormat        = VK_FORMAT_R8G8B8A8_UNORM;
78
79         const std::string                                                       vertShadernames[2]      = { "vertRef", "vertNoPer" };
80         const std::string                                                       fragShadernames[2]      = { "fragRef", "fragNoPer" };
81
82         tcu::TestLog&                                                           log                                     = m_context.getTestContext().getLog();
83
84         const bool                                                                      useMultisampling        = m_sampleCountFlagBits == VK_SAMPLE_COUNT_1_BIT ? false : true;
85
86         for (int draw = 0; draw < 2; draw++)
87         {
88                 const Unique<VkShaderModule>                                    vs                                      (createShaderModule(vk, device, m_context.getBinaryCollection().get(vertShadernames[draw].c_str()), 0));
89                 const Unique<VkShaderModule>                                    fs                                      (createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShadernames[draw].c_str()), 0));
90
91                 de::SharedPtr<Buffer>                                                   vertexBuffer;
92
93                 const CmdPoolCreateInfo                                                 cmdPoolCreateInfo       (m_context.getUniversalQueueFamilyIndex());
94                 Move<VkCommandPool>                                                             cmdPool                         = createCommandPool(vk, device, &cmdPoolCreateInfo);
95                 Move<VkCommandBuffer>                                                   cmdBuffer                       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
96
97                 Move<VkRenderPass>                                                              renderPass;
98
99                 std::vector<Move<VkImageView>>                                  colorTargetViews;
100                 std::vector<Move<VkImageView>>                                  multisampleViews;
101
102                 Move<VkFramebuffer>                                                             framebuffer;
103
104                 Move<VkPipeline>                                                                pipeline;
105                 const PipelineLayoutCreateInfo                                  pipelineLayoutCreateInfo;
106                 Move<VkPipelineLayout>                                                  pipelineLayout          = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
107
108                 const VkVertexInputAttributeDescription                 vertInAttrDescs[2]      =
109                 {
110                         { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
111                         { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(sizeof(float) * 4) }
112                 };
113
114                 // Create color buffer images
115                 {
116                         const VkExtent3D                targetImageExtent               = { static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()), 1u };
117                         const VkImageUsageFlags usage                                   = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
118                         const ImageCreateInfo   targetImageCreateInfo   (VK_IMAGE_TYPE_2D,
119                                                                                                                          imageColorFormat,
120                                                                                                                          targetImageExtent,
121                                                                                                                          1u,
122                                                                                                                          1u,
123                                                                                                                          VK_SAMPLE_COUNT_1_BIT,
124                                                                                                                          VK_IMAGE_TILING_OPTIMAL,
125                                                                                                                          usage);
126
127                         colorTargetImages[draw] = Image::createAndAlloc(vk, device, targetImageCreateInfo,
128                                                                                                                         m_context.getDefaultAllocator(),
129                                                                                                                         m_context.getUniversalQueueFamilyIndex());
130
131                         if (useMultisampling)
132                         {
133                                 const ImageCreateInfo   multisampleImageCreateInfo      (VK_IMAGE_TYPE_2D,
134                                                                                                                                          imageColorFormat,
135                                                                                                                                          targetImageExtent,
136                                                                                                                                          1u,
137                                                                                                                                          1u,
138                                                                                                                                          m_sampleCountFlagBits,
139                                                                                                                                          VK_IMAGE_TILING_OPTIMAL,
140                                                                                                                                          usage);
141
142                                 multisampleImages[draw] = Image::createAndAlloc(vk, device, multisampleImageCreateInfo,
143                                                                                                                                 m_context.getDefaultAllocator(),
144                                                                                                                                 m_context.getUniversalQueueFamilyIndex());
145                         }
146                 }
147
148                 {
149                         const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[draw]->object(),
150                                                                                                                   VK_IMAGE_VIEW_TYPE_2D,
151                                                                                                                   imageColorFormat);
152
153                         colorTargetViews.push_back(createImageView(vk, device, &colorTargetViewInfo));
154
155                         if (useMultisampling)
156                         {
157                                 const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleImages[draw]->object(),
158                                                                                                                                           VK_IMAGE_VIEW_TYPE_2D,
159                                                                                                                                           imageColorFormat);
160
161                                 multisampleViews.push_back(createImageView(vk, device, &multisamplingTargetViewInfo));
162                         }
163                 }
164
165                 // Create render pass and frame buffer.
166                 if (!m_useDynamicRendering)
167                 {
168                         RenderPassCreateInfo                            renderPassCreateInfo;
169                         std::vector<VkImageView>                        attachments;
170                         std::vector<VkAttachmentReference>      colorAttachmentRefs;
171                         std::vector<VkAttachmentReference>      multisampleAttachmentRefs;
172                         deUint32                                                        attachmentNdx           = 0;
173
174                         {
175                                 const VkAttachmentReference     colorAttachmentReference        =
176                                 {
177                                         attachmentNdx++,                                                        // uint32_t                     attachment;
178                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
179                                 };
180
181                                 colorAttachmentRefs.push_back(colorAttachmentReference);
182
183                                 renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
184                                                                                                                                                  VK_SAMPLE_COUNT_1_BIT,
185                                                                                                                                                  VK_ATTACHMENT_LOAD_OP_CLEAR,
186                                                                                                                                                  VK_ATTACHMENT_STORE_OP_STORE,
187                                                                                                                                                  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
188                                                                                                                                                  VK_ATTACHMENT_STORE_OP_DONT_CARE,
189                                                                                                                                                  VK_IMAGE_LAYOUT_UNDEFINED,
190                                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
191
192                                 if (useMultisampling)
193                                 {
194                                         const VkAttachmentReference     multiSampleAttachmentReference  =
195                                         {
196                                                 attachmentNdx++,                                                        // uint32_t                     attachment;
197                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
198                                         };
199
200                                         multisampleAttachmentRefs.push_back(multiSampleAttachmentReference);
201
202                                         renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
203                                                                                                                                                          m_sampleCountFlagBits,
204                                                                                                                                                          VK_ATTACHMENT_LOAD_OP_CLEAR,
205                                                                                                                                                          VK_ATTACHMENT_STORE_OP_DONT_CARE,
206                                                                                                                                                          VK_ATTACHMENT_LOAD_OP_DONT_CARE,
207                                                                                                                                                          VK_ATTACHMENT_STORE_OP_DONT_CARE,
208                                                                                                                                                          VK_IMAGE_LAYOUT_UNDEFINED,
209                                                                                                                                                          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
210                                 }
211                         }
212
213                         renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
214                                                                                                                            0,
215                                                                                                                            0,
216                                                                                                                            DE_NULL,
217                                                                                                                            (deUint32)colorAttachmentRefs.size(),
218                                                                                                                            useMultisampling ? &multisampleAttachmentRefs[0] : &colorAttachmentRefs[0],
219                                                                                                                            useMultisampling ? &colorAttachmentRefs[0] : DE_NULL,
220                                                                                                                            AttachmentReference(),
221                                                                                                                            0,
222                                                                                                                            DE_NULL));
223
224                         renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
225
226                         for (deUint32 frameNdx = 0; frameNdx < colorTargetViews.size(); frameNdx++)
227                         {
228                                 attachments.push_back(*colorTargetViews[frameNdx]);
229
230                                 if (useMultisampling)
231                                         attachments.push_back(*multisampleViews[frameNdx]);
232                         }
233
234                         const VkFramebufferCreateInfo   framebufferCreateInfo   =
235                         {
236                                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                      sType;
237                                 DE_NULL,                                                                        // const void*                          pNext;
238                                 0u,                                                                                     // VkFramebufferCreateFlags     flags;
239                                 *renderPass,                                                            // VkRenderPass                         renderPass;
240                                 static_cast<deUint32>(attachments.size()),      // uint32_t                                     attachmentCount;
241                                 &attachments[0],                                                        // const VkImageView*           pAttachments;
242                                 static_cast<deUint32>(m_renderSize.x()),        // uint32_t                                     width;
243                                 static_cast<deUint32>(m_renderSize.y()),        // uint32_t                                     height;
244                                 1u                                                                                      // uint32_t                                     layers;
245                         };
246
247                         framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
248                 }
249
250                 // Create vertex buffer.
251                 {
252                         const PositionColorVertex       vertices[]              =
253                         {
254                                 // The first draw is for reference image.
255                                 /*     ____            ____   */
256                                 /*    /    \          |    |  */
257                                 /*   /      \         |____|  */
258                                 /*  /        \                */
259                                 /* /__________\               */
260                                 /*                            */
261                                 /*    result        reference */
262                                 /*                            */
263                                 // In result shape the bottom vertices are deeper. When the drawn result image is a perfect square,
264                                 // and color comparison with reference image is easy to make.
265                                 PositionColorVertex(tcu::Vec4(  1.0f,                                           -1.0f,                                          0.0f,   1.0f),                                          tcu::Vec4(0.0f, m_interpolationRange, 0.0f, m_interpolationRange)),     // Top Right
266                                 PositionColorVertex(tcu::Vec4(  -1.0f,                                          -1.0f,                                          0.0f,   1.0f),                                          tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),       // Top Left
267                                 PositionColorVertex(tcu::Vec4(  draw == 0 ? 1.0f : 2.0f,        draw == 0 ? 1.0f : 2.0f,        0.0f,   draw == 0 ? 1.0f : 2.0f),       tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),       // Bottom Right
268                                 PositionColorVertex(tcu::Vec4(  draw == 0 ? -1.0f : -2.0f,      draw == 0 ? 1.0f : 2.0f,        0.0f,   draw == 0 ? 1.0f : 2.0f),       tcu::Vec4(m_interpolationRange, 0.0f, 0.0f, m_interpolationRange)),     // Bottom Left
269                                 PositionColorVertex(tcu::Vec4(  draw == 0 ? 1.0f : 2.0f,        draw == 0 ? 1.0f : 2.0f,        0.0f,   draw == 0 ? 1.0f : 2.0f),       tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),       // Bottom Right
270                                 PositionColorVertex(tcu::Vec4(  -1.0f,                                          -1.0f,                                          0.0f,   1.0f),                                          tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange))        // Top Left
271                         };
272
273                         const VkDeviceSize                      dataSize                = sizeof(vertices);
274                                                                                 vertexBuffer    = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
275                         deUint8*                                        ptr                             = static_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
276
277                         deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
278                         flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
279                 }
280
281                 // Create pipeline.
282                 {
283                         const PipelineCreateInfo::ColorBlendState::Attachment   vkCbAttachmentState;
284
285                         VkViewport                                                                                              viewport                                                = makeViewport(m_renderSize.x(), m_renderSize.y());
286                         VkRect2D                                                                                                scissor                                                 = makeRect2D(m_renderSize.x(), m_renderSize.y());
287
288                         const std::vector<deUint32>                                                             sampleMask                                              = { 0xfffffff, 0xfffffff };
289
290                         const VkVertexInputBindingDescription                                   vertexInputBindingDescription   = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
291                         PipelineCreateInfo::VertexInputState                                    vertexInputState                                = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertInAttrDescs);
292
293                         PipelineCreateInfo                                                                              pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
294
295                         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
296                         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
297                         pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
298                         pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
299                         pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
300                         pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
301                         pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
302                         pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
303                         pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_sampleCountFlagBits, false, 0.0f, sampleMask));
304
305                         VkPipelineRenderingCreateInfo                                                   renderingCreateInfo
306                         {
307                                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
308                                 DE_NULL,
309                                 0u,
310                                 1u,
311                                 &imageColorFormat,
312                                 VK_FORMAT_UNDEFINED,
313                                 VK_FORMAT_UNDEFINED
314                         };
315
316                         if (m_useDynamicRendering)
317                                 pipelineCreateInfo.pNext = &renderingCreateInfo;
318
319                         pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
320                 }
321
322                 // Draw quad and read results.
323                 {
324                         const VkQueue                                   queue                           = m_context.getUniversalQueue();
325                         const VkClearValue                              clearColor                      = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
326                         const ImageSubresourceRange             subresourceRange        (VK_IMAGE_ASPECT_COLOR_BIT);
327                         const VkRect2D                                  renderArea                      = makeRect2D(m_renderSize.x(), m_renderSize.y());
328                         const VkDeviceSize                              vertexBufferOffset      = 0;
329                         const VkBuffer                                  buffer                          = vertexBuffer->object();
330                         const VkOffset3D                                zeroOffset                      = { 0, 0, 0 };
331
332                         std::vector<VkClearValue>               clearValues                     (2, clearColor);
333
334                         clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(),
335                                 colorTargetImages[draw]->object(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
336                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
337                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
338
339                         beginCommandBuffer(vk, *cmdBuffer, 0u);
340
341                         if (m_useDynamicRendering)
342                         {
343                                 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size());
344
345                                 std::vector<VkRenderingAttachmentInfo> colorAttachments(imagesCount,
346                                 {
347                                         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,        // VkStructureType                      sType;
348                                         DE_NULL,                                                                                        // const void*                          pNext;
349                                         DE_NULL,                                                                                        // VkImageView                          imageView;
350                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                        imageLayout;
351                                         VK_RESOLVE_MODE_NONE,                                                           // VkResolveModeFlagBits        resolveMode;
352                                         DE_NULL,                                                                                        // VkImageView                          resolveImageView;
353                                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        resolveImageLayout;
354                                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp           loadOp;
355                                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp          storeOp;
356                                         clearColor                                                                                      // VkClearValue                         clearValue;
357                                 });
358
359                                 for (deUint32 i = 0; i < imagesCount; ++i)
360                                 {
361                                         if (useMultisampling)
362                                         {
363                                                 colorAttachments[i].imageView                   = *multisampleViews[i];
364                                                 colorAttachments[i].resolveMode                 = VK_RESOLVE_MODE_AVERAGE_BIT;
365                                                 colorAttachments[i].resolveImageView    = *colorTargetViews[i];
366                                         }
367                                         else
368                                         {
369                                                 colorAttachments[i].imageView                   = *colorTargetViews[i];
370                                         }
371                                 }
372
373                                 VkRenderingInfo renderingInfo
374                                 {
375                                         VK_STRUCTURE_TYPE_RENDERING_INFO,       // VkStructureType                                              sType;
376                                         DE_NULL,                                                        // const void*                                                  pNext;
377                                         0,                                                                      // VkRenderingFlagsKHR                                  flags;
378                                         renderArea,                                                     // VkRect2D                                                             renderArea;
379                                         1u,                                                                     // deUint32                                                             layerCount;
380                                         0u,                                                                     // deUint32                                                             viewMask;
381                                         imagesCount,                                            // deUint32                                                             colorAttachmentCount;
382                                         colorAttachments.data(),                        // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
383                                         DE_NULL,                                                        // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
384                                         DE_NULL,                                                        // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
385                                 };
386
387                                 // Transition Images
388                                 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
389                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
390
391                                 if (useMultisampling)
392                                 {
393                                         initialTransitionColor2DImage(vk, *cmdBuffer, multisampleImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
394                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
395                                 }
396
397                                 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
398                         }
399                         else
400                         {
401                                 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size() + multisampleViews.size());
402                                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, imagesCount, &clearValues[0]);
403                         }
404
405                         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
406                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
407                         vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
408
409                         if (m_useDynamicRendering)
410                                 endRendering(vk, *cmdBuffer);
411                         else
412                                 endRenderPass(vk, *cmdBuffer);
413
414                         endCommandBuffer(vk, *cmdBuffer);
415
416                         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
417
418                         resultPixelBufferAccesses[draw] = colorTargetImages[draw]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, zeroOffset, m_renderSize.x(), m_renderSize.y(), VK_IMAGE_ASPECT_COLOR_BIT);
419                 }
420         }
421
422         if (!tcu::floatThresholdCompare(log, "Result", "Image comparison result", resultPixelBufferAccesses[0], resultPixelBufferAccesses[1], tcu::Vec4(0.005f), tcu::COMPARE_LOG_RESULT))
423                 return tcu::TestStatus::fail("Rendered color image is not correct");
424
425         return tcu::TestStatus::pass("Success");
426 }
427
428 class MultisampleLinearInterpolationTestCase : public TestCase
429 {
430         public:
431                                                                 MultisampleLinearInterpolationTestCase  (tcu::TestContext&                              context,
432                                                                                                                                                  const char*                                    name,
433                                                                                                                                                  const char*                                    desc,
434                                                                                                                                                  const tcu::IVec2                               renderSize,
435                                                                                                                                                  const float                                    interpolationRange,
436                                                                                                                                                  const tcu::Vec2                                offset,
437                                                                                                                                                  const VkSampleCountFlagBits    sampleCountFlagBits,
438                                                                                                                                                  const bool                                             useDynamicRendering)
439                                                                 : vkt::TestCase(context, name, desc)
440                                                                 , m_renderSize                  (renderSize)
441                                                                 , m_interpolationRange  (interpolationRange)
442                                                                 , m_offset                              (offset)
443                                                                 , m_sampleCountFlagBits (sampleCountFlagBits)
444                                                                 , m_useDynamicRendering (useDynamicRendering)
445                                                                 {}
446
447                                                                 ~MultisampleLinearInterpolationTestCase (void)
448                                                                 {}
449
450         virtual void                            initPrograms            (SourceCollections& programCollection) const;
451         virtual void                            checkSupport            (Context& context) const;
452         virtual TestInstance*           createInstance          (Context& context) const;
453
454 private:
455         const tcu::IVec2                        m_renderSize;
456         const float                                     m_interpolationRange;
457         const tcu::Vec2                         m_offset;
458         const VkSampleCountFlagBits     m_sampleCountFlagBits;
459         const bool                                      m_useDynamicRendering;
460 };
461
462 void MultisampleLinearInterpolationTestCase::initPrograms (SourceCollections& programCollection) const
463 {
464         // Reference vertex shader.
465         {
466                 std::ostringstream vrt;
467
468                 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
469                         << "\n"
470                         << "layout(location = 0) in vec4 in_position;\n"
471                         << "layout(location = 1) in vec4 in_color;\n"
472                         << "layout(location = 0) out vec4 out_color;\n"
473                         << "\n"
474                         << "void main()\n"
475                         << "{\n"
476                         << "    gl_PointSize = 1.0;\n"
477                         << "    gl_Position  = in_position;\n"
478                         << "    out_color    = in_color;\n"
479                         << "}\n";
480
481                 programCollection.glslSources.add("vertRef") << glu::VertexSource(vrt.str());
482         }
483
484         // Noperspective vertex shader.
485         {
486                 std::ostringstream vrt;
487
488                 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
489                         << "\n"
490                         << "layout(location = 0) in vec4 in_position;\n"
491                         << "layout(location = 1) in vec4 in_color;\n"
492                         << "layout(location = 0) noperspective out vec4 out_color;\n"
493                         << "\n"
494                         << "void main()\n"
495                         << "{\n"
496                         << "    gl_PointSize = 1.0;\n"
497                         << "    gl_Position  = in_position;\n"
498                         << "    out_color    = in_color;\n"
499                         << "}\n";
500
501                 programCollection.glslSources.add("vertNoPer") << glu::VertexSource(vrt.str());
502         }
503
504         // Reference fragment shader.
505         {
506                 std::ostringstream frg;
507
508                 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
509                         << "layout(location = 0) in vec4 in_color;\n"
510                         << "layout(location = 0) out vec4 out_color;\n"
511                         << "void main()\n"
512                         << "{\n"
513                         << "    vec4 out_color_y = mix(vec4(0.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), gl_FragCoord.y / " << static_cast<float>(m_renderSize.y()) << " + " << m_offset.y() / static_cast<float>(m_renderSize.y()) << ");\n"
514                         << "    vec4 out_color_x = mix(vec4(1.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), gl_FragCoord.x / " << static_cast<float>(m_renderSize.x()) << " + " << m_offset.x() / static_cast<float>(m_renderSize.x()) << ");\n"
515                         << "    out_color = 0.5 * (out_color_y + out_color_x);\n"
516                         << "}\n";
517
518                 programCollection.glslSources.add("fragRef") << glu::FragmentSource(frg.str());
519         }
520
521         // Noperspective fragment shader.
522         {
523                 std::ostringstream frg;
524
525                 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
526                         << "layout(location = 0) noperspective in vec4 in_color;\n"
527                         << "layout(location = 0) out vec4 out_color;\n"
528                         << "void main()\n"
529                         << "{\n"
530                         << "    vec4 out_color_offset = interpolateAtOffset(in_color, vec2(" << m_offset.x() << ", " << m_offset.y() << "));\n"
531                         << "    vec4 out_color_sample = interpolateAtSample(in_color, gl_SampleID);\n"
532                         << "    out_color = (0.5 * (out_color_offset + out_color_sample));\n"
533                         << "    out_color /= " << m_interpolationRange << ";\n";
534
535                 // Run additional sample comparison test. If it fails, we write 1.0 to blue color channel.
536                 frg << "    if (out_color_sample != interpolateAtOffset(in_color, gl_SamplePosition - vec2(0.5)))\n"
537                         << "    {\n"
538                         << "        out_color.z = 1.0;\n"
539                         << "    }\n";
540
541                 frg << "}\n";
542
543                 programCollection.glslSources.add("fragNoPer") << glu::FragmentSource(frg.str());
544         }
545 }
546
547 void MultisampleLinearInterpolationTestCase::checkSupport (Context& context) const
548 {
549         if (!(m_sampleCountFlagBits & context.getDeviceProperties().limits.framebufferColorSampleCounts))
550                 TCU_THROW(NotSupportedError, "Multisampling with " + de::toString(m_sampleCountFlagBits) + " samples not supported");
551
552         if (m_useDynamicRendering)
553                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
554
555         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
556                 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
557         {
558                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
559         }
560 }
561
562 TestInstance* MultisampleLinearInterpolationTestCase::createInstance (Context& context) const
563 {
564         return new MultisampleLinearInterpolationTestInstance(context, m_renderSize, m_interpolationRange, m_sampleCountFlagBits, m_useDynamicRendering);
565 }
566
567 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
568 {
569         tcu::TestContext&       testCtx = testGroup->getTestContext();
570
571         struct
572         {
573                 const std::string       name;
574                 const tcu::Vec2         value;
575         } offsets[]     =
576         {
577                 { "no_offset",  tcu::Vec2(0.0f, 0.0f) },
578                 { "offset_min", tcu::Vec2(-0.5f, -0.5f) },
579                 { "offset_max", tcu::Vec2(0.4375f, 0.4375f) }
580         };
581
582         struct
583         {
584                 const std::string               name;
585                 VkSampleCountFlagBits   value;
586         } flagBits[] =
587         {
588                 { "1_sample",   VK_SAMPLE_COUNT_1_BIT },
589                 { "2_samples",  VK_SAMPLE_COUNT_2_BIT },
590                 { "4_samples",  VK_SAMPLE_COUNT_4_BIT },
591                 { "8_samples",  VK_SAMPLE_COUNT_8_BIT },
592                 { "16_samples", VK_SAMPLE_COUNT_16_BIT },
593                 { "32_samples", VK_SAMPLE_COUNT_32_BIT },
594                 { "64_samples", VK_SAMPLE_COUNT_64_BIT }
595         };
596
597         for (const auto& offset : offsets)
598         {
599                 for (const auto& flagBit : flagBits)
600                 {
601                         testGroup->addChild(new MultisampleLinearInterpolationTestCase(testCtx, (offset.name + "_" + flagBit.name).c_str(), ".", tcu::IVec2(16, 16), 1.0f, offset.value, flagBit.value, useDynamicRendering));
602                 }
603         }
604 }
605
606 }       // anonymous
607
608 tcu::TestCaseGroup*     createMultisampleLinearInterpolationTests (tcu::TestContext& testCtx, bool useDynamicRendering)
609 {
610         return createTestGroup(testCtx, "linear_interpolation", "Tests for linear interpolation decorations.", createTests, useDynamicRendering);
611 }
612
613 }       // Draw
614 }       // vkt