Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawShaderViewportIndexTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 The Android Open Source Project
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
22  * \brief Use of gl_ViewportIndex in Vertex and Tessellation Shaders
23  *        (part of VK_EXT_ShaderViewportIndexLayer)
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktDrawShaderViewportIndexTests.hpp"
27
28 #include "vktDrawBaseClass.hpp"
29 #include "vktTestCaseUtil.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "vkBuilderUtil.hpp"
42 #include "vkBufferWithMemory.hpp"
43
44 #include "tcuTestLog.hpp"
45 #include "tcuVector.hpp"
46 #include "tcuImageCompare.hpp"
47 #include "tcuTextureUtil.hpp"
48
49 #include "deUniquePtr.hpp"
50 #include "deMath.h"
51
52 #include <vector>
53 #include <memory>
54
55 namespace vkt
56 {
57 namespace Draw
58 {
59 using namespace vk;
60 using de::UniquePtr;
61 using de::MovePtr;
62 using de::SharedPtr;
63 using tcu::Vec4;
64 using tcu::Vec2;
65 using tcu::UVec2;
66 using tcu::UVec4;
67
68 namespace
69 {
70
71 enum Constants
72 {
73         MIN_MAX_VIEWPORTS = 16,         //!< Minimum number of viewports for an implementation supporting multiViewport.
74 };
75
76 struct TestParams
77 {
78         int                                             numViewports;
79         bool                                    writeFromVertex;
80         const SharedGroupParams groupParams;
81         bool                                    useTessellationShader;
82 };
83
84 template<typename T>
85 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
86 {
87         return vec.size() * sizeof(vec[0]);
88 }
89
90 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
91 {
92         const VkImageCreateInfo imageParams =
93         {
94                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType;
95                 DE_NULL,                                                                                // const void*                          pNext;
96                 (VkImageCreateFlags)0,                                                  // VkImageCreateFlags           flags;
97                 VK_IMAGE_TYPE_2D,                                                               // VkImageType                          imageType;
98                 format,                                                                                 // VkFormat                                     format;
99                 makeExtent3D(size.x(), size.y(), 1),                    // VkExtent3D                           extent;
100                 1u,                                                                                             // deUint32                                     mipLevels;
101                 1u,                                                                                             // deUint32                                     arrayLayers;
102                 VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples;
103                 VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling;
104                 usage,                                                                                  // VkImageUsageFlags            usage;
105                 VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode;
106                 0u,                                                                                             // deUint32                                     queueFamilyIndexCount;
107                 DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices;
108                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout;
109         };
110         return imageParams;
111 }
112
113 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
114                                                                            const VkDevice                               device,
115                                                                            const VkPipelineLayout               pipelineLayout,
116                                                                            const VkRenderPass                   renderPass,
117                                                                            const VkShaderModule                 vertexModule,
118                                                                            const VkShaderModule                 tessellationControlModule,
119                                                                            const VkShaderModule                 tessellationEvaluationModule,
120                                                                            const VkShaderModule                 fragmentModule,
121                                                                            const UVec2                                  renderSize,
122                                                                            const int                                    numViewports,
123                                                                            const std::vector<UVec4>             cells)
124 {
125         const VkVertexInputBindingDescription vertexInputBindingDescription =
126         {
127                 0u,                                                             // uint32_t                             binding;
128                 sizeof(PositionColorVertex),    // uint32_t                             stride;
129                 VK_VERTEX_INPUT_RATE_VERTEX,    // VkVertexInputRate    inputRate;
130         };
131
132         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
133         {
134                 {
135                         0u,                                                                     // uint32_t                     location;
136                         0u,                                                                     // uint32_t                     binding;
137                         VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat                     format;
138                         0u,                                                                     // uint32_t                     offset;
139                 },
140                 {
141                         1u,                                                                     // uint32_t                     location;
142                         0u,                                                                     // uint32_t                     binding;
143                         VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat                     format;
144                         sizeof(Vec4),                                           // uint32_t                     offset;
145                 },
146         };
147
148         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
149         {
150                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
151                 DE_NULL,                                                                                                                // const void*                                 pNext;
152                 (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
153                 1u,                                                                                                                             // uint32_t                                    vertexBindingDescriptionCount;
154                 &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
155                 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),                   // uint32_t                                    vertexAttributeDescriptionCount;
156                 vertexInputAttributeDescriptions,                                                               // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
157         };
158
159         const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
160
161         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
162         {
163                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,                                                                            // VkStructureType                             sType;
164                 DE_NULL,                                                                                                                                                                                        // const void*                                 pNext;
165                 (VkPipelineInputAssemblyStateCreateFlags)0,                                                                                                                     // VkPipelineInputAssemblyStateCreateFlags     flags;
166                 useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,        // VkPrimitiveTopology                         topology;
167                 VK_FALSE,                                                                                                                                                                                       // VkBool32                                    primitiveRestartEnable;
168         };
169
170         DE_ASSERT(numViewports == static_cast<int>(cells.size()));
171
172         std::vector<VkViewport> viewports;
173         viewports.reserve(numViewports);
174
175         std::vector<VkRect2D> rectScissors;
176         rectScissors.reserve(numViewports);
177
178         for (std::vector<UVec4>::const_iterator it = cells.begin(); it != cells.end(); ++it) {
179                 const VkViewport viewport = makeViewport(float(it->x()), float(it->y()), float(it->z()), float(it->w()), 0.0f, 1.0f);
180                 viewports.push_back(viewport);
181                 const VkRect2D rect = makeRect2D(renderSize);
182                 rectScissors.push_back(rect);
183         }
184
185         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
186         {
187                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
188                 DE_NULL,                                                                                                                // const void*                                 pNext;
189                 (VkPipelineViewportStateCreateFlags)0,                                                  // VkPipelineViewportStateCreateFlags          flags;
190                 static_cast<deUint32>(numViewports),                                                    // uint32_t                                    viewportCount;
191                 &viewports[0],                                                                                                  // const VkViewport*                           pViewports;
192                 static_cast<deUint32>(numViewports),                                                    // uint32_t                                    scissorCount;
193                 &rectScissors[0],                                                                                               // const VkRect2D*                             pScissors;
194         };
195
196         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
197         {
198                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
199                 DE_NULL,                                                                                                                // const void*                              pNext;
200                 (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
201                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
202                 VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
203                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
204                 VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
205                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
206                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
207                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
208                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
209                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
210                 1.0f,                                                                                                                   // float                                                                        lineWidth;
211         };
212
213         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
214         {
215                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
216                 DE_NULL,                                                                                                                // const void*                                                          pNext;
217                 (VkPipelineMultisampleStateCreateFlags)0,                                               // VkPipelineMultisampleStateCreateFlags        flags;
218                 VK_SAMPLE_COUNT_1_BIT,                                                                                  // VkSampleCountFlagBits                                        rasterizationSamples;
219                 VK_FALSE,                                                                                                               // VkBool32                                                                     sampleShadingEnable;
220                 0.0f,                                                                                                                   // float                                                                        minSampleShading;
221                 DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
222                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
223                 VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
224         };
225
226         const VkStencilOpState stencilOpState = makeStencilOpState(
227                 VK_STENCIL_OP_KEEP,                             // stencil fail
228                 VK_STENCIL_OP_KEEP,                             // depth & stencil pass
229                 VK_STENCIL_OP_KEEP,                             // depth only fail
230                 VK_COMPARE_OP_ALWAYS,                   // compare op
231                 0u,                                                             // compare mask
232                 0u,                                                             // write mask
233                 0u);                                                    // reference
234
235         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
236         {
237                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
238                 DE_NULL,                                                                                                                // const void*                                                          pNext;
239                 (VkPipelineDepthStencilStateCreateFlags)0,                                              // VkPipelineDepthStencilStateCreateFlags       flags;
240                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
241                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
242                 VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
243                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
244                 VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
245                 stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
246                 stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
247                 0.0f,                                                                                                                   // float                                                                        minDepthBounds;
248                 1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
249         };
250
251         const VkColorComponentFlags                                     colorComponentsAll                                      = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
252         const VkPipelineColorBlendAttachmentState       pipelineColorBlendAttachmentState       =
253         {
254                 VK_FALSE,                                               // VkBool32                                     blendEnable;
255                 VK_BLEND_FACTOR_ONE,                    // VkBlendFactor                        srcColorBlendFactor;
256                 VK_BLEND_FACTOR_ZERO,                   // VkBlendFactor                        dstColorBlendFactor;
257                 VK_BLEND_OP_ADD,                                // VkBlendOp                            colorBlendOp;
258                 VK_BLEND_FACTOR_ONE,                    // VkBlendFactor                        srcAlphaBlendFactor;
259                 VK_BLEND_FACTOR_ZERO,                   // VkBlendFactor                        dstAlphaBlendFactor;
260                 VK_BLEND_OP_ADD,                                // VkBlendOp                            alphaBlendOp;
261                 colorComponentsAll,                             // VkColorComponentFlags        colorWriteMask;
262         };
263
264         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
265         {
266                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
267                 DE_NULL,                                                                                                                // const void*                                                                  pNext;
268                 (VkPipelineColorBlendStateCreateFlags)0,                                                // VkPipelineColorBlendStateCreateFlags                 flags;
269                 VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
270                 VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
271                 1u,                                                                                                                             // deUint32                                                                             attachmentCount;
272                 &pipelineColorBlendAttachmentState,                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
273                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
274         };
275
276         const VkPipelineShaderStageCreateInfo pShaderStages[] =
277         {
278                 {
279                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
280                         DE_NULL,                                                                                                        // const void*                                                  pNext;
281                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
282                         VK_SHADER_STAGE_VERTEX_BIT,                                                                     // VkShaderStageFlagBits                                stage;
283                         vertexModule,                                                                                           // VkShaderModule                                               module;
284                         "main",                                                                                                         // const char*                                                  pName;
285                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
286                 },
287                 {
288                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
289                         DE_NULL,                                                                                                        // const void*                                                  pNext;
290                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
291                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlagBits                                stage;
292                         fragmentModule,                                                                                         // VkShaderModule                                               module;
293                         "main",                                                                                                         // const char*                                                  pName;
294                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
295                 },
296                 {
297                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
298                         DE_NULL,                                                                                                        // const void*                                                  pNext;
299                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
300                         VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,                                       // VkShaderStageFlagBits                                stage;
301                         tessellationControlModule,                                                                      // VkShaderModule                                               module;
302                         "main",                                                                                                         // const char*                                                  pName;
303                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
304                 },
305                 {
306                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
307                         DE_NULL,                                                                                                        // const void*                                                  pNext;
308                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
309                         VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,                            // VkShaderStageFlagBits                                stage;
310                         tessellationEvaluationModule,                                                           // VkShaderModule                                               module;
311                         "main",                                                                                                         // const char*                                                  pName;
312                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
313                 },
314         };
315
316         const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
317         {
318                 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
319                 DE_NULL,                                                                                                                // const void*                                                          pNext;
320                 (VkPipelineTessellationStateCreateFlags)0,                                              // VkPipelineTessellationStateCreateFlags       flags;
321                 3,                                                                                                                              // uint32_t                                                                     patchControlPoints;
322         };
323
324         VkGraphicsPipelineCreateInfo graphicsPipelineInfo
325         {
326                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                        // VkStructureType                                                                      sType;
327                 DE_NULL,                                                                                                                        // const void*                                                                          pNext;
328                 (VkPipelineCreateFlags)0,                                                                                       // VkPipelineCreateFlags                                                        flags;
329                 useTessellationShaders ? deUint32(4) : deUint32(2),                                     // deUint32                                                                                     stageCount;
330                 pShaderStages,                                                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
331                 &vertexInputStateInfo,                                                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
332                 &pipelineInputAssemblyStateInfo,                                                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
333                 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL,      // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
334                 &pipelineViewportStateInfo,                                                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
335                 &pipelineRasterizationStateInfo,                                                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
336                 &pipelineMultisampleStateInfo,                                                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
337                 &pipelineDepthStencilStateInfo,                                                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
338                 &pipelineColorBlendStateInfo,                                                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
339                 DE_NULL,                                                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
340                 pipelineLayout,                                                                                                         // VkPipelineLayout                                                                     layout;
341                 renderPass,                                                                                                                     // VkRenderPass                                                                         renderPass;
342                 0u,                                                                                                                                     // deUint32                                                                                     subpass;
343                 DE_NULL,                                                                                                                        // VkPipeline                                                                           basePipelineHandle;
344                 0,                                                                                                                                      // deInt32                                                                                      basePipelineIndex;
345         };
346
347 #ifndef CTS_USES_VULKANSC
348         VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
349         VkPipelineRenderingCreateInfoKHR renderingCreateInfo
350         {
351                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
352                 DE_NULL,
353                 0u,
354                 1u,
355                 &colorAttachmentFormat,
356                 VK_FORMAT_UNDEFINED,
357                 VK_FORMAT_UNDEFINED
358         };
359
360         // when pipeline is created without render pass we are using dynamic rendering
361         if (renderPass == DE_NULL)
362                 graphicsPipelineInfo.pNext = &renderingCreateInfo;
363 #endif // CTS_USES_VULKANSC
364
365         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
366 }
367
368 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
369 {
370         const int numCols               = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
371         const int numRows               = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
372         const int rectWidth             = renderSize.x() / numCols;
373         const int rectHeight    = renderSize.y() / numRows;
374
375         std::vector<UVec4> cells;
376         cells.reserve(numCells);
377
378         int x = 0;
379         int y = 0;
380
381         for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
382         {
383                 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
384                 if (nextRow)
385                 {
386                         x  = 0;
387                         y += rectHeight;
388                 }
389
390                 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
391
392                 x += rectWidth;
393         }
394
395         return cells;
396 }
397
398 std::vector<Vec4> generateColors (const int numColors)
399 {
400         const Vec4 colors[] =
401         {
402                 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
403                 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
404                 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
405                 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
406                 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
407                 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
408                 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
409                 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
410                 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
411                 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
412                 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
413                 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
414                 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
415                 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
416                 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
417                 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
418         };
419
420         DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors));
421
422         return std::vector<Vec4>(colors, colors + numColors);
423 }
424
425 //! Renders a colorful grid of rectangles.
426 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat      format,
427                                                                                   const UVec2&                          renderSize,
428                                                                                   const Vec4&                           clearColor,
429                                                                                   const std::vector<UVec4>&     cells,
430                                                                                   const std::vector<Vec4>&      cellColors)
431 {
432         DE_ASSERT(cells.size() == cellColors.size());
433
434         tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
435         tcu::clear(image.getAccess(), clearColor);
436
437         for (std::size_t i = 0; i < cells.size(); ++i)
438         {
439                 const UVec4& cell = cells[i];
440                 tcu::clear(
441                         tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
442                         cellColors[i]);
443         }
444
445         return image;
446 }
447
448 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams)
449 {
450         // Vertex shader
451         {
452                 std::ostringstream src;
453                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
454                         << "#extension GL_ARB_shader_viewport_layer_array : require\n"
455                         << "\n"
456                         << "layout(location = 0) in  vec4 in_position;\n"
457                         << "layout(location = 1) in  vec4 in_color;\n"
458                         << "layout(location = 0) out vec4 out_color;\n"
459                         << "\n"
460                         << "void main(void)\n"
461                         << "{\n"
462                         << "    gl_ViewportIndex = gl_VertexIndex / 6;\n"
463                         << "    gl_Position = in_position;\n"
464                         << "    out_color = in_color;\n"
465                         << "}\n";
466
467                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
468         }
469
470         // Fragment shader
471         {
472                 std::ostringstream src;
473                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
474                         << "\n"
475                         << "layout(location = 0) in  vec4 in_color;\n"
476                         << "layout(location = 0) out vec4 out_color;\n"
477                         << "\n"
478                         << "void main(void)\n"
479                         << "{\n"
480                         << "    out_color = in_color;\n"
481                         << "}\n";
482
483                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
484         }
485 }
486
487 void initFragmentTestPrograms (SourceCollections& programCollection, const TestParams testParams)
488 {
489         // Vertex shader.
490         {
491                 std::ostringstream src;
492                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
493                         << "#extension GL_ARB_shader_viewport_layer_array : require\n"
494                         << "\n"
495                         << "layout(location = 0) in  vec4 in_position;\n"
496                         << "layout(location = 1) in  vec4 in_color;\n"
497                         << "layout(location = 0) out vec4 out_color;\n"
498                         << "\n"
499                         << "void main(void)\n"
500                         << "{\n"
501                         << (testParams.writeFromVertex ? "    gl_ViewportIndex = gl_VertexIndex / 6;\n" : "")
502                         << "    gl_Position = in_position;\n"
503                         << "    out_color = in_color;\n"
504                         << "}\n";
505
506                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
507         }
508
509         // Fragment shader
510         {
511                 // Ignore input color and choose one using the viewport index.
512                 std::ostringstream src;
513                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
514                         << "\n"
515                         << "layout(location = 0) in  vec4 in_color;\n"
516                         << "layout(location = 0) out vec4 out_color;\n"
517                         << "layout(set=0, binding=0) uniform Colors {\n"
518                         << "    vec4 color[" << testParams.numViewports << "];\n"
519                         << "};\n"
520                         << "\n"
521                         << "void main(void)\n"
522                         << "{\n"
523                         << "    out_color = color[gl_ViewportIndex];\n"
524                         << "}\n";
525
526                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
527         }
528 }
529
530 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams)
531 {
532         // Vertex shader
533         {
534                 std::ostringstream src;
535                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
536                         << "\n"
537                         << "layout(location = 0) in  vec4 in_position;\n"
538                         << "layout(location = 1) in  vec4 in_color;\n"
539                         << "layout(location = 0) out vec4 out_color;\n"
540                         << "\n"
541                         << "void main(void)\n"
542                         << "{\n"
543                         << "    gl_Position = in_position;\n"
544                         << "    out_color = in_color;\n"
545                         << "}\n";
546
547                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
548         }
549
550         // Tessellation control shader
551         {
552                 std::ostringstream src;
553                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554                         << "\n"
555                         << "layout(vertices = 3) out;\n"
556                         << "\n"
557                         << "layout(location = 0) in  vec4 in_color[];\n"
558                         << "layout(location = 0) out vec4 out_color[];\n"
559                         << "\n"
560                         << "void main(void)\n"
561                         << "{\n"
562                         << "    if (gl_InvocationID == 0) {\n"
563                         << "        gl_TessLevelInner[0] = 1.0;\n"
564                         << "        gl_TessLevelInner[1] = 1.0;\n"
565                         << "        gl_TessLevelOuter[0] = 1.0;\n"
566                         << "        gl_TessLevelOuter[1] = 1.0;\n"
567                         << "        gl_TessLevelOuter[2] = 1.0;\n"
568                         << "        gl_TessLevelOuter[3] = 1.0;\n"
569                         << "    }\n"
570                         << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
571                         << "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
572                         << "}\n";
573
574                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
575         }
576
577         // Tessellation evaluation shader
578         {
579                 std::ostringstream src;
580                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
581                         << "#extension GL_ARB_shader_viewport_layer_array : require\n"
582                         << "\n"
583                         << "layout(triangles, equal_spacing, cw) in;\n"
584                         << "\n"
585                         << "layout(location = 0) in  vec4 in_color[];\n"
586                         << "layout(location = 0) out vec4 out_color;\n"
587                         << "\n"
588                         << "void main(void)\n"
589                         << "{\n"
590                         << "    gl_ViewportIndex = gl_PrimitiveID / 2;\n"
591                         << "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
592                         << "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
593                         << "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
594                         << "\n"
595                         << "    out_color = in_color[0] * gl_TessCoord.x +\n"
596                         << "                in_color[1] * gl_TessCoord.y +\n"
597                         << "                in_color[2] * gl_TessCoord.z;\n"
598                         << "}\n";
599
600                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
601         }
602
603         // Fragment shader
604         {
605                 std::ostringstream src;
606                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
607                         << "\n"
608                         << "layout(location = 0) in  vec4 in_color;\n"
609                         << "layout(location = 0) out vec4 out_color;\n"
610                         << "\n"
611                         << "void main(void)\n"
612                         << "{\n"
613                         << "    out_color = in_color;\n"
614                         << "}\n";
615
616                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
617         }
618 }
619
620 std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors)
621 {
622         // Two triangles for each color (viewport).
623         std::size_t total = colors.size() * 6;
624
625         std::vector<PositionColorVertex> result;
626         result.reserve(total);
627
628         for (std::size_t i = 0; i < total; ++i)
629         {
630                 Vec4 pos;
631                 pos.z() = 0.0;
632                 pos.w() = 1.0;
633
634                 switch (i % 6) {
635                 case 0: pos.xy() = Vec2(-1.0,  1.0); break;
636                 case 1: pos.xy() = Vec2( 1.0,  1.0); break;
637                 case 2: pos.xy() = Vec2(-1.0, -1.0); break;
638                 case 3: pos.xy() = Vec2( 1.0, -1.0); break;
639                 case 4: pos.xy() = Vec2( 1.0,  1.0); break;
640                 case 5: pos.xy() = Vec2(-1.0, -1.0); break;
641                 }
642
643                 result.push_back(PositionColorVertex(pos, colors[i/6]));
644         }
645
646         return result;
647 }
648
649 // Renderer generates two triangles per viewport, each pair using a different color. The
650 // numViewports are positioned to form a grid.
651 class Renderer
652 {
653 public:
654         enum Shader {
655                 VERTEX,
656                 TESSELLATION,
657                 FRAGMENT,
658         };
659
660         Renderer (Context&                                              context,
661                           const UVec2&                                  renderSize,
662                           const TestParams&                             testParams,
663                           const std::vector<UVec4>&             cells,
664                           const VkFormat                                colorFormat,
665                           const Vec4&                                   clearColor,
666                           const std::vector<Vec4>&              colors,
667                           const Shader                                  shader)
668                 : m_groupParams                         (testParams.groupParams)
669                 , m_renderSize                          (renderSize)
670                 , m_colorFormat                         (colorFormat)
671                 , m_colorSubresourceRange       (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
672                 , m_clearValue                          (makeClearValueColor(clearColor))
673                 , m_numViewports                        (testParams.numViewports)
674                 , m_colors                                      (colors)
675                 , m_vertices                            (generateVertices(colors))
676                 , m_shader                                      (shader)
677         {
678                 const DeviceInterface&          vk                                      = context.getDeviceInterface();
679                 const VkDevice                          device                          = context.getDevice();
680                 const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
681                 Allocator&                                      allocator                       = context.getDefaultAllocator();
682                 const VkDeviceSize                      vertexBufferSize    = sizeInBytes(m_vertices);
683
684                 m_colorImage            = makeImage                                     (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
685                 m_colorImageAlloc       = bindImage                                     (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
686                 m_colorAttachment       = makeImageView                         (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
687
688                 m_vertexBuffer          = Buffer::createAndAlloc        (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
689
690                 {
691                         deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
692                         flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
693                 }
694
695                 if (shader == TESSELLATION)
696                 {
697                         m_tessellationControlModule             = createShaderModule    (vk, device, context.getBinaryCollection().get("tesc"), 0u);
698                         m_tessellationEvaluationModule  = createShaderModule    (vk, device, context.getBinaryCollection().get("tese"), 0u);
699                 }
700
701                 m_vertexModule          = createShaderModule    (vk, device, context.getBinaryCollection().get("vert"), 0u);
702                 m_fragmentModule        = createShaderModule    (vk, device, context.getBinaryCollection().get("frag"), 0u);
703
704                 if (!m_groupParams->useDynamicRendering)
705                 {
706                         m_renderPass    = makeRenderPass                (vk, device, m_colorFormat);
707
708                         m_framebuffer   = makeFramebuffer               (vk, device, *m_renderPass, m_colorAttachment.get(),
709                                                                                                          static_cast<deUint32>(m_renderSize.x()),  static_cast<deUint32>(m_renderSize.y()));
710                 }
711
712                 if (shader == FRAGMENT)
713                 {
714                         vk::DescriptorSetLayoutBuilder builder;
715                         builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
716                         m_descriptorSetLayout = builder.build(vk, device);
717                 }
718
719                 m_pipelineLayout        = makePipelineLayout    (vk, device, (shader == FRAGMENT ? m_descriptorSetLayout.get() : DE_NULL));
720                 m_pipeline                      = makeGraphicsPipeline  (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
721                                                                                                          *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells);
722                 m_cmdPool                       = createCommandPool             (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
723                 m_cmdBuffer                     = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
724                 m_secCmdBuffer          = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
725         }
726
727         void draw (Context& context, const VkBuffer colorBuffer)
728         {
729                 const DeviceInterface&  vk                      = context.getDeviceInterface();
730                 const VkDevice                  device          = context.getDevice();
731                 const VkQueue                   queue           = context.getUniversalQueue();
732                 const VkRect2D                  renderArea
733                 {
734                         makeOffset2D(0, 0),
735                         makeExtent2D(m_renderSize.x(), m_renderSize.y()),
736                 };
737
738 #ifndef CTS_USES_VULKANSC
739                 if (m_groupParams->useSecondaryCmdBuffer)
740                 {
741                         // record secondary command buffer
742                         if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
743                         {
744                                 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
745                                 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
746                                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
747                         }
748                         else
749                                 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
750
751                         drawCommands(context, *m_secCmdBuffer);
752
753                         if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
754                                 endRendering(vk, *m_secCmdBuffer);
755
756                         endCommandBuffer(vk, *m_secCmdBuffer);
757
758                         // record primary command buffer
759                         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
760
761                         preRenderCommands(context, *m_cmdBuffer);
762
763                         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
764                                 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
765                                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
766
767                         vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
768
769                         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
770                                 endRendering(vk, *m_cmdBuffer);
771
772                         postRenderCommands(context, colorBuffer);
773                         endCommandBuffer(vk, *m_cmdBuffer);
774                 }
775                 else if (m_groupParams->useDynamicRendering)
776                 {
777                         beginCommandBuffer(vk, *m_cmdBuffer);
778
779                         preRenderCommands(context, *m_cmdBuffer);
780                         beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
781                                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
782                         drawCommands(context, *m_cmdBuffer);
783                         endRendering(vk, *m_cmdBuffer);
784                         postRenderCommands(context, colorBuffer);
785
786                         endCommandBuffer(vk, *m_cmdBuffer);
787                 }
788 #endif // CTS_USES_VULKANSC
789
790                 if (!m_groupParams->useDynamicRendering)
791                 {
792                         beginCommandBuffer(vk, *m_cmdBuffer);
793
794                         preRenderCommands(context, *m_cmdBuffer);
795                         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_clearValue);
796                         drawCommands(context, *m_cmdBuffer);
797                         endRenderPass(vk, *m_cmdBuffer);
798                         postRenderCommands(context, colorBuffer);
799
800                         endCommandBuffer(vk, *m_cmdBuffer);
801                 }
802
803                 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
804         }
805
806 protected:
807
808 #ifndef CTS_USES_VULKANSC
809         void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
810         {
811                 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
812                 {
813                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,                // VkStructureType                                      sType;
814                         DE_NULL,                                                                                                                                // const void*                                          pNext;
815                         renderingFlags,                                                                                                                 // VkRenderingFlagsKHR                          flags;
816                         0u,                                                                                                                                             // uint32_t                                                     viewMask;
817                         1u,                                                                                                                                             // uint32_t                                                     colorAttachmentCount;
818                         &m_colorFormat,                                                                                                                 // const VkFormat*                                      pColorAttachmentFormats;
819                         VK_FORMAT_UNDEFINED,                                                                                                    // VkFormat                                                     depthAttachmentFormat;
820                         VK_FORMAT_UNDEFINED,                                                                                                    // VkFormat                                                     stencilAttachmentFormat;
821                         VK_SAMPLE_COUNT_1_BIT,                                                                                                  // VkSampleCountFlagBits                        rasterizationSamples;
822                 };
823                 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
824
825                 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
826                 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
827                         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
828
829                 const VkCommandBufferBeginInfo commandBufBeginParams
830                 {
831                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                                                    // VkStructureType                                      sType;
832                         DE_NULL,                                                                                                                                // const void*                                          pNext;
833                         usageFlags,                                                                                                                             // VkCommandBufferUsageFlags            flags;
834                         &bufferInheritanceInfo
835                 };
836
837                 const DeviceInterface& vk = context.getDeviceInterface();
838                 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
839         }
840 #endif // CTS_USES_VULKANSC
841
842         void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
843         {
844                 if (m_groupParams->useDynamicRendering)
845                 {
846                         const DeviceInterface& vk = context.getDeviceInterface();
847                         initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
848                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
849                 }
850         }
851
852         void postRenderCommands(Context& context, VkBuffer colorBuffer) const
853         {
854                 const DeviceInterface& vk = context.getDeviceInterface();
855                 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()));
856         }
857
858         void drawCommands(Context& context, VkCommandBuffer cmdBuffer)
859         {
860                 const DeviceInterface&  vk                                      = context.getDeviceInterface();
861                 const VkDevice                  device                          = context.getDevice();
862                 Allocator&                              allocator                       = context.getDefaultAllocator();
863                 const VkBuffer                  vertexBuffer            = m_vertexBuffer->object();
864                 const VkDeviceSize              vertexBufferOffset      = 0ull;
865
866                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
867                 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
868
869                 // Prepare colors buffer if needed.
870                 if (m_shader == FRAGMENT)
871                 {
872                         // Create buffer.
873                         const auto      colorsBufferSize = m_colors.size() * sizeof(decltype(m_colors)::value_type);
874                         const auto      colorsBufferCreateInfo = vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(colorsBufferSize), vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
875                         m_colorsBuffer = SharedPtr<BufferWithMemory>(new vk::BufferWithMemory{ vk, device, allocator, colorsBufferCreateInfo, MemoryRequirement::HostVisible });
876
877                         // Copy colors and flush allocation.
878                         auto& colorsBufferAlloc = m_colorsBuffer->getAllocation();
879                         deMemcpy(colorsBufferAlloc.getHostPtr(), m_colors.data(), colorsBufferSize);
880                         vk::flushAlloc(vk, device, colorsBufferAlloc);
881
882                         // Descriptor pool.
883                         DescriptorPoolBuilder poolBuilder;
884                         poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
885                         m_descriptorPool = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
886
887                         // Descriptor set.
888                         m_descriptorSet = vk::makeDescriptorSet(vk, device, m_descriptorPool.get(), m_descriptorSetLayout.get());
889
890                         // Update and bind descriptor set.
891                         const auto                                              colorsBufferDescriptorInfo = vk::makeDescriptorBufferInfo(m_colorsBuffer->get(), 0ull, VK_WHOLE_SIZE);
892                         vk::DescriptorSetUpdateBuilder  updateBuilder;
893                         updateBuilder.writeSingle(m_descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &colorsBufferDescriptorInfo);
894                         updateBuilder.update(vk, device);
895
896                         vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
897                 }
898
899                 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u);   // two triangles per viewport
900         }
901
902 private:
903         const SharedGroupParams                                 m_groupParams;
904         const UVec2                                                             m_renderSize;
905         const VkFormat                                                  m_colorFormat;
906         const VkImageSubresourceRange                   m_colorSubresourceRange;
907         const VkClearValue                                              m_clearValue;
908         const int                                                               m_numViewports;
909         const std::vector<Vec4>                                 m_colors;
910         const std::vector<PositionColorVertex>  m_vertices;
911         const Shader                                                    m_shader;
912
913         Move<VkImage>                                                   m_colorImage;
914         MovePtr<Allocation>                                             m_colorImageAlloc;
915         Move<VkImageView>                                               m_colorAttachment;
916         SharedPtr<BufferWithMemory>                             m_colorsBuffer;
917         SharedPtr<Buffer>                                               m_vertexBuffer;
918         Move<VkShaderModule>                                    m_vertexModule;
919         Move<VkShaderModule>                                    m_tessellationControlModule;
920         Move<VkShaderModule>                                    m_tessellationEvaluationModule;
921         Move<VkShaderModule>                                    m_fragmentModule;
922         Move<VkRenderPass>                                              m_renderPass;
923         Move<VkFramebuffer>                                             m_framebuffer;
924         Move<VkDescriptorPool>                                  m_descriptorPool;
925         Move<VkDescriptorSet>                                   m_descriptorSet;
926         Move<VkDescriptorSetLayout>                             m_descriptorSetLayout;
927         Move<VkPipelineLayout>                                  m_pipelineLayout;
928         Move<VkPipeline>                                                m_pipeline;
929         Move<VkCommandPool>                                             m_cmdPool;
930         Move<VkCommandBuffer>                                   m_cmdBuffer;
931         Move<VkCommandBuffer>                                   m_secCmdBuffer;
932
933         // "deleted"
934                                 Renderer        (const Renderer&);
935         Renderer&       operator=       (const Renderer&);
936 };
937
938 tcu::TestStatus testVertexFragmentShader (Context& context, const TestParams& testParams, Renderer::Shader shader)
939 {
940         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
941         const VkDevice                                  device                          = context.getDevice();
942         Allocator&                                              allocator                       = context.getDefaultAllocator();
943
944         const UVec2                                             renderSize                      (128, 128);
945         const VkFormat                                  colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
946         const Vec4                                              clearColor                      (0.5f, 0.5f, 0.5f, 1.0f);
947         const std::vector<Vec4>                 colors                          = generateColors(testParams.numViewports);
948         const std::vector<UVec4>                cells                           = generateGrid(testParams.numViewports, renderSize);
949
950         const VkDeviceSize                              colorBufferSize         = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
951
952         const SharedPtr<Buffer>                 colorBuffer                     = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
953
954         // Zero buffer.
955         {
956                 const Allocation alloc = colorBuffer->getBoundMemory();
957                 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
958                 flushAlloc(vk, device, alloc);
959         }
960
961         {
962                 context.getTestContext().getLog()
963                         << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
964                         << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
965         }
966
967         // Draw
968         {
969                 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, shader);
970                 renderer.draw(context, colorBuffer->object());
971         }
972
973         // Log image
974         {
975                 const Allocation alloc = colorBuffer->getBoundMemory();
976                 invalidateAlloc(vk, device, alloc);
977
978                 const tcu::ConstPixelBufferAccess       resultImage             (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
979                 const tcu::TextureLevel                         referenceImage  = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
980
981                 // Images should now match.
982                 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
983                         TCU_FAIL("Rendered image is not correct");
984         }
985
986         return tcu::TestStatus::pass("OK");
987 }
988
989 tcu::TestStatus testVertexShader (Context& context, const TestParams testParams)
990 {
991         return testVertexFragmentShader(context, testParams, Renderer::VERTEX);
992 }
993
994 tcu::TestStatus testFragmentShader (Context& context, const TestParams testParams)
995 {
996         return testVertexFragmentShader(context, testParams, Renderer::FRAGMENT);
997 }
998
999 tcu::TestStatus testTessellationShader (Context& context, const TestParams testParams)
1000 {
1001         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
1002         const VkDevice                                  device                          = context.getDevice();
1003         Allocator&                                              allocator                       = context.getDefaultAllocator();
1004
1005         const UVec2                                             renderSize                      (128, 128);
1006         const VkFormat                                  colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
1007         const Vec4                                              clearColor                      (0.5f, 0.5f, 0.5f, 1.0f);
1008         const std::vector<Vec4>                 colors                          = generateColors(testParams.numViewports);
1009         const std::vector<UVec4>                cells                           = generateGrid(testParams.numViewports, renderSize);
1010
1011         const VkDeviceSize                              colorBufferSize         = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
1012
1013         const SharedPtr<Buffer>                 colorBuffer                     = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
1014
1015         // Zero buffer.
1016         {
1017                 const Allocation alloc = colorBuffer->getBoundMemory();
1018                 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1019                 flushAlloc(vk, device, alloc);
1020         }
1021
1022         {
1023                 context.getTestContext().getLog()
1024                         << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
1025                         << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
1026         }
1027
1028         // Draw
1029         {
1030                 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION);
1031                 renderer.draw(context, colorBuffer->object());
1032         }
1033
1034         // Log image
1035         {
1036                 const Allocation alloc = colorBuffer->getBoundMemory();
1037                 invalidateAlloc(vk, device, alloc);
1038
1039                 const tcu::ConstPixelBufferAccess       resultImage             (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
1040                 const tcu::TextureLevel                         referenceImage  = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
1041
1042                 // Images should now match.
1043                 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1044                         TCU_FAIL("Rendered image is not correct");
1045         }
1046
1047         return tcu::TestStatus::pass("OK");
1048 }
1049
1050 void checkSupport (Context& context, TestParams params)
1051 {
1052         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
1053         context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
1054
1055         if (context.getDeviceProperties().limits.maxViewports < MIN_MAX_VIEWPORTS)
1056                 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
1057
1058         if (params.useTessellationShader)
1059                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1060
1061         if (params.groupParams->useDynamicRendering)
1062                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1063 }
1064
1065 } // anonymous
1066
1067 tcu::TestCaseGroup* createShaderViewportIndexTests      (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1068 {
1069         MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index", ""));
1070
1071         TestParams testParams
1072         {
1073                 1,                                              // int                                  numViewports;
1074                 false,                                  // bool                                 writeFromVertex;
1075                 groupParams,                    // SharedGroupParams    groupParams;
1076                 false                                   // bool                                 useTessellationShader;
1077         };
1078
1079         for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1080                 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(testParams.numViewports), "", checkSupport, initVertexTestPrograms, testVertexShader, testParams);
1081
1082         testParams.numViewports = 1;
1083         addFunctionCaseWithPrograms(group.get(), "fragment_shader_implicit", "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1084         testParams.writeFromVertex = true;
1085         for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1086                 addFunctionCaseWithPrograms(group.get(), "fragment_shader_" + de::toString(testParams.numViewports), "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1087         testParams.writeFromVertex = false;
1088
1089         testParams.useTessellationShader = true;
1090         for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1091                 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(testParams.numViewports), "", checkSupport, initTessellationTestPrograms, testTessellationShader, testParams);
1092
1093         return group.release();
1094 }
1095
1096 } // Draw
1097 } // vkt