Merge vk-gl-cts/vulkan-cts-1.3.2 into vk-gl-cts/vulkan-cts-1.3.3
[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 #ifndef CTS_USES_VULKANSC
306                         VkPipelineRenderingCreateInfo                                                   renderingCreateInfo
307                         {
308                                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
309                                 DE_NULL,
310                                 0u,
311                                 1u,
312                                 &imageColorFormat,
313                                 VK_FORMAT_UNDEFINED,
314                                 VK_FORMAT_UNDEFINED
315                         };
316
317                         if (m_useDynamicRendering)
318                                 pipelineCreateInfo.pNext = &renderingCreateInfo;
319 #endif // CTS_USES_VULKANSC
320
321                         pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
322                 }
323
324                 // Draw quad and read results.
325                 {
326                         const VkQueue                                   queue                           = m_context.getUniversalQueue();
327                         const VkClearValue                              clearColor                      = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
328                         const ImageSubresourceRange             subresourceRange        (VK_IMAGE_ASPECT_COLOR_BIT);
329                         const VkRect2D                                  renderArea                      = makeRect2D(m_renderSize.x(), m_renderSize.y());
330                         const VkDeviceSize                              vertexBufferOffset      = 0;
331                         const VkBuffer                                  buffer                          = vertexBuffer->object();
332                         const VkOffset3D                                zeroOffset                      = { 0, 0, 0 };
333
334                         std::vector<VkClearValue>               clearValues                     (2, clearColor);
335
336                         clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(),
337                                 colorTargetImages[draw]->object(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
338                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
339                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
340
341                         beginCommandBuffer(vk, *cmdBuffer, 0u);
342
343 #ifndef CTS_USES_VULKANSC
344                         if (m_useDynamicRendering)
345                         {
346                                 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size());
347
348                                 std::vector<VkRenderingAttachmentInfo> colorAttachments(imagesCount,
349                                 {
350                                         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,        // VkStructureType                      sType;
351                                         DE_NULL,                                                                                        // const void*                          pNext;
352                                         DE_NULL,                                                                                        // VkImageView                          imageView;
353                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                        imageLayout;
354                                         VK_RESOLVE_MODE_NONE,                                                           // VkResolveModeFlagBits        resolveMode;
355                                         DE_NULL,                                                                                        // VkImageView                          resolveImageView;
356                                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        resolveImageLayout;
357                                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp           loadOp;
358                                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp          storeOp;
359                                         clearColor                                                                                      // VkClearValue                         clearValue;
360                                 });
361
362                                 for (deUint32 i = 0; i < imagesCount; ++i)
363                                 {
364                                         if (useMultisampling)
365                                         {
366                                                 colorAttachments[i].imageView                   = *multisampleViews[i];
367                                                 colorAttachments[i].resolveMode                 = VK_RESOLVE_MODE_AVERAGE_BIT;
368                                                 colorAttachments[i].resolveImageView    = *colorTargetViews[i];
369                                         }
370                                         else
371                                         {
372                                                 colorAttachments[i].imageView                   = *colorTargetViews[i];
373                                         }
374                                 }
375
376                                 VkRenderingInfo renderingInfo
377                                 {
378                                         VK_STRUCTURE_TYPE_RENDERING_INFO,       // VkStructureType                                              sType;
379                                         DE_NULL,                                                        // const void*                                                  pNext;
380                                         0,                                                                      // VkRenderingFlagsKHR                                  flags;
381                                         renderArea,                                                     // VkRect2D                                                             renderArea;
382                                         1u,                                                                     // deUint32                                                             layerCount;
383                                         0u,                                                                     // deUint32                                                             viewMask;
384                                         imagesCount,                                            // deUint32                                                             colorAttachmentCount;
385                                         colorAttachments.data(),                        // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
386                                         DE_NULL,                                                        // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
387                                         DE_NULL,                                                        // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
388                                 };
389
390                                 // Transition Images
391                                 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
392                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
393
394                                 if (useMultisampling)
395                                 {
396                                         initialTransitionColor2DImage(vk, *cmdBuffer, multisampleImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
397                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
398                                 }
399
400                                 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
401                         }
402                         else
403 #endif // CTS_USES_VULKANSC
404                         {
405                                 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size() + multisampleViews.size());
406                                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, imagesCount, &clearValues[0]);
407                         }
408
409                         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
410                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
411                         vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
412
413 #ifndef CTS_USES_VULKANSC
414                         if (m_useDynamicRendering)
415                                 endRendering(vk, *cmdBuffer);
416                         else
417 #endif // CTS_USES_VULKANSC
418                                 endRenderPass(vk, *cmdBuffer);
419
420                         endCommandBuffer(vk, *cmdBuffer);
421
422                         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
423
424                         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);
425                 }
426         }
427
428         if (!tcu::floatThresholdCompare(log, "Result", "Image comparison result", resultPixelBufferAccesses[0], resultPixelBufferAccesses[1], tcu::Vec4(0.005f), tcu::COMPARE_LOG_RESULT))
429                 return tcu::TestStatus::fail("Rendered color image is not correct");
430
431         return tcu::TestStatus::pass("Success");
432 }
433
434 class MultisampleLinearInterpolationTestCase : public TestCase
435 {
436         public:
437                                                                 MultisampleLinearInterpolationTestCase  (tcu::TestContext&                              context,
438                                                                                                                                                  const char*                                    name,
439                                                                                                                                                  const char*                                    desc,
440                                                                                                                                                  const tcu::IVec2                               renderSize,
441                                                                                                                                                  const float                                    interpolationRange,
442                                                                                                                                                  const tcu::Vec2                                offset,
443                                                                                                                                                  const VkSampleCountFlagBits    sampleCountFlagBits,
444                                                                                                                                                  const bool                                             useDynamicRendering)
445                                                                 : vkt::TestCase(context, name, desc)
446                                                                 , m_renderSize                  (renderSize)
447                                                                 , m_interpolationRange  (interpolationRange)
448                                                                 , m_offset                              (offset)
449                                                                 , m_sampleCountFlagBits (sampleCountFlagBits)
450                                                                 , m_useDynamicRendering (useDynamicRendering)
451                                                                 {}
452
453                                                                 ~MultisampleLinearInterpolationTestCase (void)
454                                                                 {}
455
456         virtual void                            initPrograms            (SourceCollections& programCollection) const;
457         virtual void                            checkSupport            (Context& context) const;
458         virtual TestInstance*           createInstance          (Context& context) const;
459
460 private:
461         const tcu::IVec2                        m_renderSize;
462         const float                                     m_interpolationRange;
463         const tcu::Vec2                         m_offset;
464         const VkSampleCountFlagBits     m_sampleCountFlagBits;
465         const bool                                      m_useDynamicRendering;
466 };
467
468 void MultisampleLinearInterpolationTestCase::initPrograms (SourceCollections& programCollection) const
469 {
470         // Reference vertex shader.
471         {
472                 std::ostringstream vrt;
473
474                 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
475                         << "\n"
476                         << "layout(location = 0) in vec4 in_position;\n"
477                         << "layout(location = 1) in vec4 in_color;\n"
478                         << "layout(location = 0) out vec4 out_color;\n"
479                         << "\n"
480                         << "void main()\n"
481                         << "{\n"
482                         << "    gl_PointSize = 1.0;\n"
483                         << "    gl_Position  = in_position;\n"
484                         << "    out_color    = in_color;\n"
485                         << "}\n";
486
487                 programCollection.glslSources.add("vertRef") << glu::VertexSource(vrt.str());
488         }
489
490         // Noperspective vertex shader.
491         {
492                 std::ostringstream vrt;
493
494                 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
495                         << "\n"
496                         << "layout(location = 0) in vec4 in_position;\n"
497                         << "layout(location = 1) in vec4 in_color;\n"
498                         << "layout(location = 0) noperspective out vec4 out_color;\n"
499                         << "\n"
500                         << "void main()\n"
501                         << "{\n"
502                         << "    gl_PointSize = 1.0;\n"
503                         << "    gl_Position  = in_position;\n"
504                         << "    out_color    = in_color;\n"
505                         << "}\n";
506
507                 programCollection.glslSources.add("vertNoPer") << glu::VertexSource(vrt.str());
508         }
509
510         // Reference fragment shader.
511         {
512                 std::ostringstream frg;
513
514                 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
515                         << "layout(location = 0) in vec4 in_color;\n"
516                         << "layout(location = 0) out vec4 out_color;\n"
517                         << "void main()\n"
518                         << "{\n"
519                         << "    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"
520                         << "    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"
521                         << "    out_color = 0.5 * (out_color_y + out_color_x);\n"
522                         << "}\n";
523
524                 programCollection.glslSources.add("fragRef") << glu::FragmentSource(frg.str());
525         }
526
527         // Noperspective fragment shader.
528         {
529                 std::ostringstream frg;
530
531                 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
532                         << "layout(location = 0) noperspective in vec4 in_color;\n"
533                         << "layout(location = 0) out vec4 out_color;\n"
534                         << "void main()\n"
535                         << "{\n"
536                         << "    vec4 out_color_offset = interpolateAtOffset(in_color, vec2(" << m_offset.x() << ", " << m_offset.y() << "));\n"
537                         << "    vec4 out_color_sample = interpolateAtSample(in_color, gl_SampleID);\n"
538                         << "    out_color = (0.5 * (out_color_offset + out_color_sample));\n"
539                         << "    out_color /= " << m_interpolationRange << ";\n";
540
541                 // Run additional sample comparison test. If it fails, we write 1.0 to blue color channel.
542                 frg << "    if (out_color_sample != interpolateAtOffset(in_color, gl_SamplePosition - vec2(0.5)))\n"
543                         << "    {\n"
544                         << "        out_color.z = 1.0;\n"
545                         << "    }\n";
546
547                 frg << "}\n";
548
549                 programCollection.glslSources.add("fragNoPer") << glu::FragmentSource(frg.str());
550         }
551 }
552
553 void MultisampleLinearInterpolationTestCase::checkSupport (Context& context) const
554 {
555         if (!(m_sampleCountFlagBits & context.getDeviceProperties().limits.framebufferColorSampleCounts))
556                 TCU_THROW(NotSupportedError, "Multisampling with " + de::toString(m_sampleCountFlagBits) + " samples not supported");
557 #ifndef CTS_USES_VULKANSC
558         if (m_useDynamicRendering)
559                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
560
561         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
562                 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
563         {
564                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
565         }
566 #endif // CTS_USES_VULKANSC
567 }
568
569 TestInstance* MultisampleLinearInterpolationTestCase::createInstance (Context& context) const
570 {
571         return new MultisampleLinearInterpolationTestInstance(context, m_renderSize, m_interpolationRange, m_sampleCountFlagBits, m_useDynamicRendering);
572 }
573
574 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
575 {
576         tcu::TestContext&       testCtx = testGroup->getTestContext();
577
578         struct
579         {
580                 const std::string       name;
581                 const tcu::Vec2         value;
582         } offsets[]     =
583         {
584                 { "no_offset",  tcu::Vec2(0.0f, 0.0f) },
585                 { "offset_min", tcu::Vec2(-0.5f, -0.5f) },
586                 { "offset_max", tcu::Vec2(0.4375f, 0.4375f) }
587         };
588
589         struct
590         {
591                 const std::string               name;
592                 VkSampleCountFlagBits   value;
593         } flagBits[] =
594         {
595                 { "1_sample",   VK_SAMPLE_COUNT_1_BIT },
596                 { "2_samples",  VK_SAMPLE_COUNT_2_BIT },
597                 { "4_samples",  VK_SAMPLE_COUNT_4_BIT },
598                 { "8_samples",  VK_SAMPLE_COUNT_8_BIT },
599                 { "16_samples", VK_SAMPLE_COUNT_16_BIT },
600                 { "32_samples", VK_SAMPLE_COUNT_32_BIT },
601                 { "64_samples", VK_SAMPLE_COUNT_64_BIT }
602         };
603
604         for (const auto& offset : offsets)
605         {
606                 for (const auto& flagBit : flagBits)
607                 {
608                         testGroup->addChild(new MultisampleLinearInterpolationTestCase(testCtx, (offset.name + "_" + flagBit.name).c_str(), ".", tcu::IVec2(16, 16), 1.0f, offset.value, flagBit.value, useDynamicRendering));
609                 }
610         }
611 }
612
613 }       // anonymous
614
615 tcu::TestCaseGroup*     createMultisampleLinearInterpolationTests (tcu::TestContext& testCtx, bool useDynamicRendering)
616 {
617         return createTestGroup(testCtx, "linear_interpolation", "Tests for linear interpolation decorations.", createTests, useDynamicRendering);
618 }
619
620 }       // Draw
621 }       // vkt