Merge vk-gl-cts/vulkan-cts-1.3.3 into vk-gl-cts/vulkan-cts-1.3.4
[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 SharedGroupParams                groupParams)
49                                                 : vkt::TestInstance             (context)
50                                                 , m_renderSize                  (renderSize)
51                                                 , m_interpolationRange  (interpolationRange)
52                                                 , m_sampleCountFlagBits (sampleCountFlagBits)
53                                                 , m_groupParams                 (groupParams)
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 SharedGroupParams         m_groupParams;
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                 Move<VkCommandBuffer>                                                   secCmdBuffer;
97
98                 Move<VkRenderPass>                                                              renderPass;
99
100                 std::vector<Move<VkImageView>>                                  colorTargetViews;
101                 std::vector<Move<VkImageView>>                                  multisampleViews;
102
103                 Move<VkFramebuffer>                                                             framebuffer;
104
105                 Move<VkPipeline>                                                                pipeline;
106                 const PipelineLayoutCreateInfo                                  pipelineLayoutCreateInfo;
107                 Move<VkPipelineLayout>                                                  pipelineLayout          = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
108
109                 const VkVertexInputAttributeDescription                 vertInAttrDescs[2]      =
110                 {
111                         { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
112                         { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(sizeof(float) * 4) }
113                 };
114
115                 // Create color buffer images
116                 {
117                         const VkExtent3D                targetImageExtent               = { static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()), 1u };
118                         const VkImageUsageFlags usage                                   = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
119                         const ImageCreateInfo   targetImageCreateInfo   (VK_IMAGE_TYPE_2D,
120                                                                                                                          imageColorFormat,
121                                                                                                                          targetImageExtent,
122                                                                                                                          1u,
123                                                                                                                          1u,
124                                                                                                                          VK_SAMPLE_COUNT_1_BIT,
125                                                                                                                          VK_IMAGE_TILING_OPTIMAL,
126                                                                                                                          usage);
127
128                         colorTargetImages[draw] = Image::createAndAlloc(vk, device, targetImageCreateInfo,
129                                                                                                                         m_context.getDefaultAllocator(),
130                                                                                                                         m_context.getUniversalQueueFamilyIndex());
131
132                         if (useMultisampling)
133                         {
134                                 const ImageCreateInfo   multisampleImageCreateInfo      (VK_IMAGE_TYPE_2D,
135                                                                                                                                          imageColorFormat,
136                                                                                                                                          targetImageExtent,
137                                                                                                                                          1u,
138                                                                                                                                          1u,
139                                                                                                                                          m_sampleCountFlagBits,
140                                                                                                                                          VK_IMAGE_TILING_OPTIMAL,
141                                                                                                                                          usage);
142
143                                 multisampleImages[draw] = Image::createAndAlloc(vk, device, multisampleImageCreateInfo,
144                                                                                                                                 m_context.getDefaultAllocator(),
145                                                                                                                                 m_context.getUniversalQueueFamilyIndex());
146                         }
147                 }
148
149                 {
150                         const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[draw]->object(),
151                                                                                                                   VK_IMAGE_VIEW_TYPE_2D,
152                                                                                                                   imageColorFormat);
153
154                         colorTargetViews.push_back(createImageView(vk, device, &colorTargetViewInfo));
155
156                         if (useMultisampling)
157                         {
158                                 const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleImages[draw]->object(),
159                                                                                                                                           VK_IMAGE_VIEW_TYPE_2D,
160                                                                                                                                           imageColorFormat);
161
162                                 multisampleViews.push_back(createImageView(vk, device, &multisamplingTargetViewInfo));
163                         }
164                 }
165
166                 // Create render pass and frame buffer.
167                 if (!m_groupParams->useDynamicRendering)
168                 {
169                         RenderPassCreateInfo                            renderPassCreateInfo;
170                         std::vector<VkImageView>                        attachments;
171                         std::vector<VkAttachmentReference>      colorAttachmentRefs;
172                         std::vector<VkAttachmentReference>      multisampleAttachmentRefs;
173                         deUint32                                                        attachmentNdx           = 0;
174
175                         {
176                                 const VkAttachmentReference     colorAttachmentReference        =
177                                 {
178                                         attachmentNdx++,                                                        // uint32_t                     attachment;
179                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
180                                 };
181
182                                 colorAttachmentRefs.push_back(colorAttachmentReference);
183
184                                 renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
185                                                                                                                                                  VK_SAMPLE_COUNT_1_BIT,
186                                                                                                                                                  VK_ATTACHMENT_LOAD_OP_CLEAR,
187                                                                                                                                                  VK_ATTACHMENT_STORE_OP_STORE,
188                                                                                                                                                  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
189                                                                                                                                                  VK_ATTACHMENT_STORE_OP_DONT_CARE,
190                                                                                                                                                  VK_IMAGE_LAYOUT_UNDEFINED,
191                                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
192
193                                 if (useMultisampling)
194                                 {
195                                         const VkAttachmentReference     multiSampleAttachmentReference  =
196                                         {
197                                                 attachmentNdx++,                                                        // uint32_t                     attachment;
198                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
199                                         };
200
201                                         multisampleAttachmentRefs.push_back(multiSampleAttachmentReference);
202
203                                         renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
204                                                                                                                                                          m_sampleCountFlagBits,
205                                                                                                                                                          VK_ATTACHMENT_LOAD_OP_CLEAR,
206                                                                                                                                                          VK_ATTACHMENT_STORE_OP_DONT_CARE,
207                                                                                                                                                          VK_ATTACHMENT_LOAD_OP_DONT_CARE,
208                                                                                                                                                          VK_ATTACHMENT_STORE_OP_DONT_CARE,
209                                                                                                                                                          VK_IMAGE_LAYOUT_UNDEFINED,
210                                                                                                                                                          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
211                                 }
212                         }
213
214                         renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
215                                                                                                                            0,
216                                                                                                                            0,
217                                                                                                                            DE_NULL,
218                                                                                                                            (deUint32)colorAttachmentRefs.size(),
219                                                                                                                            useMultisampling ? &multisampleAttachmentRefs[0] : &colorAttachmentRefs[0],
220                                                                                                                            useMultisampling ? &colorAttachmentRefs[0] : DE_NULL,
221                                                                                                                            AttachmentReference(),
222                                                                                                                            0,
223                                                                                                                            DE_NULL));
224
225                         renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
226
227                         for (deUint32 frameNdx = 0; frameNdx < colorTargetViews.size(); frameNdx++)
228                         {
229                                 attachments.push_back(*colorTargetViews[frameNdx]);
230
231                                 if (useMultisampling)
232                                         attachments.push_back(*multisampleViews[frameNdx]);
233                         }
234
235                         const VkFramebufferCreateInfo   framebufferCreateInfo   =
236                         {
237                                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                      sType;
238                                 DE_NULL,                                                                        // const void*                          pNext;
239                                 0u,                                                                                     // VkFramebufferCreateFlags     flags;
240                                 *renderPass,                                                            // VkRenderPass                         renderPass;
241                                 static_cast<deUint32>(attachments.size()),      // uint32_t                                     attachmentCount;
242                                 &attachments[0],                                                        // const VkImageView*           pAttachments;
243                                 static_cast<deUint32>(m_renderSize.x()),        // uint32_t                                     width;
244                                 static_cast<deUint32>(m_renderSize.y()),        // uint32_t                                     height;
245                                 1u                                                                                      // uint32_t                                     layers;
246                         };
247
248                         framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
249                 }
250
251                 // Create vertex buffer.
252                 {
253                         const PositionColorVertex       vertices[]              =
254                         {
255                                 // The first draw is for reference image.
256                                 /*     ____            ____   */
257                                 /*    /    \          |    |  */
258                                 /*   /      \         |____|  */
259                                 /*  /        \                */
260                                 /* /__________\               */
261                                 /*                            */
262                                 /*    result        reference */
263                                 /*                            */
264                                 // In result shape the bottom vertices are deeper. When the drawn result image is a perfect square,
265                                 // and color comparison with reference image is easy to make.
266                                 PositionColorVertex(tcu::Vec4(  1.0f,                                           -1.0f,                                          0.0f,   1.0f),                                          tcu::Vec4(0.0f, m_interpolationRange, 0.0f, m_interpolationRange)),     // Top Right
267                                 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
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.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),       // Bottom Right
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.0f, 0.0f, m_interpolationRange)),     // Bottom Left
270                                 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
271                                 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
272                         };
273
274                         const VkDeviceSize                      dataSize                = sizeof(vertices);
275                                                                                 vertexBuffer    = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
276                         deUint8*                                        ptr                             = static_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
277
278                         deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
279                         flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
280                 }
281
282                 // Create pipeline.
283                 {
284                         const PipelineCreateInfo::ColorBlendState::Attachment   vkCbAttachmentState;
285
286                         VkViewport                                                                                              viewport                                                = makeViewport(m_renderSize.x(), m_renderSize.y());
287                         VkRect2D                                                                                                scissor                                                 = makeRect2D(m_renderSize.x(), m_renderSize.y());
288
289                         const std::vector<deUint32>                                                             sampleMask                                              = { 0xfffffff, 0xfffffff };
290
291                         const VkVertexInputBindingDescription                                   vertexInputBindingDescription   = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
292                         PipelineCreateInfo::VertexInputState                                    vertexInputState                                = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertInAttrDescs);
293
294                         PipelineCreateInfo                                                                              pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
295
296                         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
297                         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
298                         pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
299                         pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
300                         pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
301                         pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
302                         pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
303                         pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
304                         pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_sampleCountFlagBits, false, 0.0f, sampleMask));
305
306 #ifndef CTS_USES_VULKANSC
307                         VkPipelineRenderingCreateInfo                                                   renderingCreateInfo
308                         {
309                                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
310                                 DE_NULL,
311                                 0u,
312                                 1u,
313                                 &imageColorFormat,
314                                 VK_FORMAT_UNDEFINED,
315                                 VK_FORMAT_UNDEFINED
316                         };
317
318                         if (m_groupParams->useDynamicRendering)
319                                 pipelineCreateInfo.pNext = &renderingCreateInfo;
320 #endif // CTS_USES_VULKANSC
321
322                         pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
323                 }
324
325                 // Draw quad and read results.
326                 {
327                         const VkQueue                                   queue                           = m_context.getUniversalQueue();
328                         const VkClearValue                              clearColor                      = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
329                         const ImageSubresourceRange             subresourceRange        (VK_IMAGE_ASPECT_COLOR_BIT);
330                         const VkRect2D                                  renderArea                      = makeRect2D(m_renderSize.x(), m_renderSize.y());
331                         const VkBuffer                                  buffer                          = vertexBuffer->object();
332                         const VkOffset3D                                zeroOffset                      = { 0, 0, 0 };
333
334                         std::vector<VkClearValue>               clearValues                     (2, clearColor);
335
336                         auto drawCommands = [&](VkCommandBuffer cmdBuff)
337                         {
338                                 const VkDeviceSize vertexBufferOffset = 0;
339                                 vk.cmdBindVertexBuffers(cmdBuff, 0, 1, &buffer, &vertexBufferOffset);
340                                 vk.cmdBindPipeline(cmdBuff, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
341                                 vk.cmdDraw(cmdBuff, 6u, 1u, 0u, 0u);
342                         };
343
344                         clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(),
345                                 colorTargetImages[draw]->object(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
346                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
347                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
348
349 #ifndef CTS_USES_VULKANSC
350                         auto preRenderBarriers = [&]()
351                         {
352                                 // Transition Images
353                                 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
354                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
355
356                                 if (useMultisampling)
357                                 {
358                                         initialTransitionColor2DImage(vk, *cmdBuffer, multisampleImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
359                                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
360                                 }
361                         };
362
363                         if (m_groupParams->useDynamicRendering)
364                         {
365                                 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size());
366
367                                 std::vector<VkRenderingAttachmentInfo> colorAttachments(imagesCount,
368                                 {
369                                         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,        // VkStructureType                      sType;
370                                         DE_NULL,                                                                                        // const void*                          pNext;
371                                         DE_NULL,                                                                                        // VkImageView                          imageView;
372                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                        imageLayout;
373                                         VK_RESOLVE_MODE_NONE,                                                           // VkResolveModeFlagBits        resolveMode;
374                                         DE_NULL,                                                                                        // VkImageView                          resolveImageView;
375                                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        resolveImageLayout;
376                                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp           loadOp;
377                                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp          storeOp;
378                                         clearColor                                                                                      // VkClearValue                         clearValue;
379                                 });
380
381                                 for (deUint32 i = 0; i < imagesCount; ++i)
382                                 {
383                                         if (useMultisampling)
384                                         {
385                                                 colorAttachments[i].imageView                   = *multisampleViews[i];
386                                                 colorAttachments[i].resolveMode                 = VK_RESOLVE_MODE_AVERAGE_BIT;
387                                                 colorAttachments[i].resolveImageView    = *colorTargetViews[i];
388                                         }
389                                         else
390                                         {
391                                                 colorAttachments[i].imageView                   = *colorTargetViews[i];
392                                         }
393                                 }
394
395                                 VkRenderingInfo renderingInfo
396                                 {
397                                         VK_STRUCTURE_TYPE_RENDERING_INFO,       // VkStructureType                                              sType;
398                                         DE_NULL,                                                        // const void*                                                  pNext;
399                                         0,                                                                      // VkRenderingFlagsKHR                                  flags;
400                                         renderArea,                                                     // VkRect2D                                                             renderArea;
401                                         1u,                                                                     // deUint32                                                             layerCount;
402                                         0u,                                                                     // deUint32                                                             viewMask;
403                                         imagesCount,                                            // deUint32                                                             colorAttachmentCount;
404                                         colorAttachments.data(),                        // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
405                                         DE_NULL,                                                        // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
406                                         DE_NULL,                                                        // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
407                                 };
408
409                                 if (m_groupParams->useSecondaryCmdBuffer)
410                                 {
411                                         VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
412                                         {
413                                                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,                // VkStructureType                                              sType;
414                                                 DE_NULL,                                                                                                                                // const void*                                                  pNext;
415                                                 0u,                                                                                                                                             // VkRenderingFlagsKHR                                  flags;
416                                                 0u,                                                                                                                                             // uint32_t                                                             viewMask;
417                                                 1u,                                                                                                                                             // uint32_t                                                             colorAttachmentCount;
418                                                 &imageColorFormat,                                                                                                              // const VkFormat*                                              pColorAttachmentFormats;
419                                                 VK_FORMAT_UNDEFINED,                                                                                                    // VkFormat                                                             depthAttachmentFormat;
420                                                 VK_FORMAT_UNDEFINED,                                                                                                    // VkFormat                                                             stencilAttachmentFormat;
421                                                 m_sampleCountFlagBits                                                                                                   // VkSampleCountFlagBits                                rasterizationSamples;
422                                         };
423
424                                         const VkCommandBufferInheritanceInfo    bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
425                                         VkCommandBufferBeginInfo                                commandBufBeginParams
426                                         {
427                                                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                                                    // VkStructureType                                      sType;
428                                                 DE_NULL,                                                                                                                                // const void*                                          pNext;
429                                                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,                                                    // VkCommandBufferUsageFlags            flags;
430                                                 &bufferInheritanceInfo
431                                         };
432
433                                         secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
434
435                                         // record secondary command buffer
436                                         if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
437                                         {
438                                                 inheritanceRenderingInfo.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
439                                                 VK_CHECK(vk.beginCommandBuffer(*secCmdBuffer, &commandBufBeginParams));
440                                                 vk.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
441                                         }
442                                         else
443                                         {
444                                                 commandBufBeginParams.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
445                                                 VK_CHECK(vk.beginCommandBuffer(*secCmdBuffer, &commandBufBeginParams));
446                                         }
447
448                                         drawCommands(*secCmdBuffer);
449
450                                         if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
451                                                 endRendering(vk, *secCmdBuffer);
452
453                                         endCommandBuffer(vk, *secCmdBuffer);
454
455                                         // record primary command buffer
456                                         beginCommandBuffer(vk, *cmdBuffer, 0u);
457
458                                         preRenderBarriers();
459
460                                         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
461                                         {
462                                                 renderingInfo.flags = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
463                                                 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
464                                         }
465                                         vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
466
467                                         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
468                                                 endRendering(vk, *cmdBuffer);
469                                         endCommandBuffer(vk, *cmdBuffer);
470                                 }
471                                 else
472                                 {
473                                         beginCommandBuffer(vk, *cmdBuffer, 0u);
474                                         preRenderBarriers();
475
476                                         vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
477                                         drawCommands(*cmdBuffer);
478                                         endRendering(vk, *cmdBuffer);
479
480                                         endCommandBuffer(vk, *cmdBuffer);
481                                 }
482                         }
483                         else
484 #endif // CTS_USES_VULKANSC
485                         {
486                                 beginCommandBuffer(vk, *cmdBuffer, 0u);
487
488                                 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size() + multisampleViews.size());
489
490                                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, imagesCount, &clearValues[0]);
491                                 drawCommands(*cmdBuffer);
492                                 endRenderPass(vk, *cmdBuffer);
493
494                                 endCommandBuffer(vk, *cmdBuffer);
495                         }
496
497                         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
498
499                         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);
500                 }
501         }
502
503         if (!tcu::floatThresholdCompare(log, "Result", "Image comparison result", resultPixelBufferAccesses[0], resultPixelBufferAccesses[1], tcu::Vec4(0.005f), tcu::COMPARE_LOG_RESULT))
504                 return tcu::TestStatus::fail("Rendered color image is not correct");
505
506         return tcu::TestStatus::pass("Success");
507 }
508
509 class MultisampleLinearInterpolationTestCase : public TestCase
510 {
511         public:
512                                                                 MultisampleLinearInterpolationTestCase  (tcu::TestContext&                              context,
513                                                                                                                                                  const char*                                    name,
514                                                                                                                                                  const char*                                    desc,
515                                                                                                                                                  const tcu::IVec2                               renderSize,
516                                                                                                                                                  const float                                    interpolationRange,
517                                                                                                                                                  const tcu::Vec2                                offset,
518                                                                                                                                                  const VkSampleCountFlagBits    sampleCountFlagBits,
519                                                                                                                                                  const SharedGroupParams                groupParams)
520                                                                 : vkt::TestCase(context, name, desc)
521                                                                 , m_renderSize                  (renderSize)
522                                                                 , m_interpolationRange  (interpolationRange)
523                                                                 , m_offset                              (offset)
524                                                                 , m_sampleCountFlagBits (sampleCountFlagBits)
525                                                                 , m_groupParams                 (groupParams)
526                                                                 {}
527
528                                                                 ~MultisampleLinearInterpolationTestCase (void)
529                                                                 {}
530
531         virtual void                            initPrograms            (SourceCollections& programCollection) const;
532         virtual void                            checkSupport            (Context& context) const;
533         virtual TestInstance*           createInstance          (Context& context) const;
534
535 private:
536         const tcu::IVec2                        m_renderSize;
537         const float                                     m_interpolationRange;
538         const tcu::Vec2                         m_offset;
539         const VkSampleCountFlagBits     m_sampleCountFlagBits;
540         const SharedGroupParams         m_groupParams;
541 };
542
543 void MultisampleLinearInterpolationTestCase::initPrograms (SourceCollections& programCollection) const
544 {
545         // Reference vertex shader.
546         {
547                 std::ostringstream vrt;
548
549                 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
550                         << "\n"
551                         << "layout(location = 0) in vec4 in_position;\n"
552                         << "layout(location = 1) in vec4 in_color;\n"
553                         << "layout(location = 0) out vec4 out_color;\n"
554                         << "\n"
555                         << "void main()\n"
556                         << "{\n"
557                         << "    gl_PointSize = 1.0;\n"
558                         << "    gl_Position  = in_position;\n"
559                         << "    out_color    = in_color;\n"
560                         << "}\n";
561
562                 programCollection.glslSources.add("vertRef") << glu::VertexSource(vrt.str());
563         }
564
565         // Noperspective vertex shader.
566         {
567                 std::ostringstream vrt;
568
569                 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
570                         << "\n"
571                         << "layout(location = 0) in vec4 in_position;\n"
572                         << "layout(location = 1) in vec4 in_color;\n"
573                         << "layout(location = 0) noperspective out vec4 out_color;\n"
574                         << "\n"
575                         << "void main()\n"
576                         << "{\n"
577                         << "    gl_PointSize = 1.0;\n"
578                         << "    gl_Position  = in_position;\n"
579                         << "    out_color    = in_color;\n"
580                         << "}\n";
581
582                 programCollection.glslSources.add("vertNoPer") << glu::VertexSource(vrt.str());
583         }
584
585         // Reference fragment shader.
586         {
587                 std::ostringstream frg;
588
589                 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
590                         << "layout(location = 0) in vec4 in_color;\n"
591                         << "layout(location = 0) out vec4 out_color;\n"
592                         << "void main()\n"
593                         << "{\n"
594                         << "    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"
595                         << "    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"
596                         << "    out_color = 0.5 * (out_color_y + out_color_x);\n"
597                         << "}\n";
598
599                 programCollection.glslSources.add("fragRef") << glu::FragmentSource(frg.str());
600         }
601
602         // Noperspective fragment shader.
603         {
604                 std::ostringstream frg;
605
606                 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
607                         << "layout(location = 0) noperspective in vec4 in_color;\n"
608                         << "layout(location = 0) out vec4 out_color;\n"
609                         << "void main()\n"
610                         << "{\n"
611                         << "    vec4 out_color_offset = interpolateAtOffset(in_color, vec2(" << m_offset.x() << ", " << m_offset.y() << "));\n"
612                         << "    vec4 out_color_sample = interpolateAtSample(in_color, gl_SampleID);\n"
613                         << "    out_color = (0.5 * (out_color_offset + out_color_sample));\n"
614                         << "    out_color /= " << m_interpolationRange << ";\n";
615
616                 // Run additional sample comparison test. If it fails, we write 1.0 to blue color channel.
617                 frg << "    if (out_color_sample != interpolateAtOffset(in_color, gl_SamplePosition - vec2(0.5)))\n"
618                         << "    {\n"
619                         << "        out_color.z = 1.0;\n"
620                         << "    }\n";
621
622                 frg << "}\n";
623
624                 programCollection.glslSources.add("fragNoPer") << glu::FragmentSource(frg.str());
625         }
626 }
627
628 void MultisampleLinearInterpolationTestCase::checkSupport (Context& context) const
629 {
630         if (!(m_sampleCountFlagBits & context.getDeviceProperties().limits.framebufferColorSampleCounts))
631                 TCU_THROW(NotSupportedError, "Multisampling with " + de::toString(m_sampleCountFlagBits) + " samples not supported");
632
633 #ifndef CTS_USES_VULKANSC
634         if (m_groupParams->useDynamicRendering)
635                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
636
637         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
638                 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
639         {
640                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
641         }
642 #endif // CTS_USES_VULKANSC
643 }
644
645 TestInstance* MultisampleLinearInterpolationTestCase::createInstance (Context& context) const
646 {
647         return new MultisampleLinearInterpolationTestInstance(context, m_renderSize, m_interpolationRange, m_sampleCountFlagBits, m_groupParams);
648 }
649
650 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
651 {
652         tcu::TestContext&       testCtx = testGroup->getTestContext();
653
654         struct
655         {
656                 const std::string       name;
657                 const tcu::Vec2         value;
658         } offsets[]     =
659         {
660                 { "no_offset",  tcu::Vec2(0.0f, 0.0f) },
661                 { "offset_min", tcu::Vec2(-0.5f, -0.5f) },
662                 { "offset_max", tcu::Vec2(0.4375f, 0.4375f) }
663         };
664
665         struct
666         {
667                 const std::string               name;
668                 VkSampleCountFlagBits   value;
669         } flagBits[] =
670         {
671                 { "1_sample",   VK_SAMPLE_COUNT_1_BIT },
672                 { "2_samples",  VK_SAMPLE_COUNT_2_BIT },
673                 { "4_samples",  VK_SAMPLE_COUNT_4_BIT },
674                 { "8_samples",  VK_SAMPLE_COUNT_8_BIT },
675                 { "16_samples", VK_SAMPLE_COUNT_16_BIT },
676                 { "32_samples", VK_SAMPLE_COUNT_32_BIT },
677                 { "64_samples", VK_SAMPLE_COUNT_64_BIT }
678         };
679
680         for (const auto& offset : offsets)
681         {
682                 for (const auto& flagBit : flagBits)
683                 {
684                         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
685                         if (groupParams->useSecondaryCmdBuffer && (flagBit.value > VK_SAMPLE_COUNT_4_BIT))
686                                 break;
687
688                         testGroup->addChild(new MultisampleLinearInterpolationTestCase(testCtx, (offset.name + "_" + flagBit.name).c_str(), ".", tcu::IVec2(16, 16), 1.0f, offset.value, flagBit.value, groupParams));
689                 }
690         }
691 }
692
693 }       // anonymous
694
695 tcu::TestCaseGroup*     createMultisampleLinearInterpolationTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
696 {
697         return createTestGroup(testCtx, "linear_interpolation", "Tests for linear interpolation decorations.", createTests, groupParams);
698 }
699
700 }       // Draw
701 }       // vkt