Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawMultiExtTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Valve Corporation.
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 Test for VK_EXT_multi_draw
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawMultiExtTests.hpp"
26
27 #include "vkTypeUtil.hpp"
28 #include "vkImageWithMemory.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35
36 #include "tcuTexture.hpp"
37 #include "tcuMaybe.hpp"
38 #include "tcuImageCompare.hpp"
39
40 #include "deUniquePtr.hpp"
41 #include "deMath.h"
42 #include "deRandom.hpp"
43
44 #include <vector>
45 #include <sstream>
46 #include <algorithm>
47 #include <iterator>
48 #include <limits>
49
50 using namespace vk;
51
52 namespace vkt
53 {
54 namespace Draw
55 {
56
57 namespace
58 {
59
60 // Normal or indexed draws.
61 enum class DrawType { NORMAL = 0, INDEXED };
62
63 // How to apply the vertex offset in indexed draws.
64 enum class VertexOffsetType
65 {
66         MIXED = 0,                      // Do not use pVertexOffset and mix values in struct-indicated offsets.
67         CONSTANT_RANDOM,        // Use a constant value for pVertexOffset and fill offset struct members with random values.
68         CONSTANT_PACK,          // Use a constant value for pVertexOffset and a stride that removes the vertex offset member in structs.
69 };
70
71 // Triangle mesh type.
72 enum class MeshType { MOSAIC = 0, OVERLAPPING };
73
74 // Vertex offset parameters.
75 struct VertexOffsetParams
76 {
77         VertexOffsetType        offsetType;
78         deUint32                        offset;
79 };
80
81 // Test parameters.
82 struct TestParams
83 {
84         MeshType                                                meshType;
85         DrawType                                                drawType;
86         deUint32                                                drawCount;
87         deUint32                                                instanceCount;
88         deUint32                                                firstInstance;
89         deUint32                                                stride;
90         tcu::Maybe<VertexOffsetParams>  vertexOffset;   // Only used for indexed draws.
91         deUint32                                                seed;
92         bool                                                    useTessellation;
93         bool                                                    useGeometry;
94         bool                                                    multiview;
95         const SharedGroupParams                 groupParams;
96
97         deUint32 maxInstanceIndex () const
98         {
99                 if (instanceCount == 0u)
100                         return 0u;
101                 return (firstInstance + instanceCount - 1u);
102         }
103 };
104
105 // For the color attachment. Must match what the fragment shader expects.
106 VkFormat getColorFormat ()
107 {
108         return VK_FORMAT_R8G8B8A8_UINT;
109 }
110
111 // Compatible with getColorFormat() but better when used with the image logging facilities.
112 VkFormat getVerificationFormat ()
113 {
114         return VK_FORMAT_R8G8B8A8_UNORM;
115 }
116
117 // Find a suitable format for the depth/stencil buffer.
118 VkFormat chooseDepthStencilFormat (const InstanceInterface& vki, VkPhysicalDevice physDev)
119 {
120         // The spec mandates support for one of these two formats.
121         const VkFormat candidates[] = { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
122
123         for (const auto& format : candidates)
124         {
125                 const auto properties = getPhysicalDeviceFormatProperties(vki, physDev, format);
126                 if ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u)
127                         return format;
128         }
129
130         TCU_FAIL("No suitable depth/stencil format found");
131         return VK_FORMAT_UNDEFINED; // Unreachable.
132 }
133
134 // Format used when verifying the stencil aspect.
135 VkFormat getStencilVerificationFormat ()
136 {
137         return VK_FORMAT_S8_UINT;
138 }
139
140 deUint32 getTriangleCount ()
141 {
142         return 1024u;   // This matches the minumum allowed limit for maxMultiDrawCount, so we can submit a single triangle per draw call.
143 }
144
145 // Base class for creating triangles.
146 class TriangleGenerator
147 {
148 public:
149         // Append a new triangle for ID (x, y).
150         virtual void appendTriangle(deUint32 x, deUint32 y, std::vector<tcu::Vec4>& vertices) = 0;
151 };
152
153 // Class that helps creating triangle vertices for each framebuffer pixel, forming a mosaic of triangles.
154 class TriangleMosaicGenerator : public TriangleGenerator
155 {
156 private:
157         // Normalized width and height taking into account the framebuffer's width and height are two units (from -1 to 1).
158         float   m_pixelWidth;
159         float   m_pixelHeight;
160
161         float   m_deltaX;
162         float   m_deltaY;
163
164 public:
165         TriangleMosaicGenerator (deUint32 width, deUint32 height)
166                 : m_pixelWidth  (2.0f / static_cast<float>(width))
167                 , m_pixelHeight (2.0f / static_cast<float>(height))
168                 , m_deltaX              (m_pixelWidth * 0.25f)
169                 , m_deltaY              (m_pixelHeight * 0.25f)
170         {}
171
172         // Creates a triangle for framebuffer pixel (x, y) around its center. Appends the triangle vertices to the given list.
173         void appendTriangle(deUint32 x, deUint32 y, std::vector<tcu::Vec4>& vertices) override
174         {
175                 // Pixel center.
176                 const float coordX      = (static_cast<float>(x) + 0.5f) * m_pixelWidth - 1.0f;
177                 const float coordY      = (static_cast<float>(y) + 0.5f) * m_pixelHeight - 1.0f;
178
179                 // Triangle around it.
180                 const float topY        = coordY - m_deltaY;
181                 const float bottomY     = coordY + m_deltaY;
182
183                 const float leftX       = coordX - m_deltaX;
184                 const float rightX      = coordX + m_deltaX;
185
186                 // Note: clockwise.
187                 vertices.emplace_back(leftX,    bottomY,        0.0f, 1.0f);
188                 vertices.emplace_back(coordX,   topY,           0.0f, 1.0f);
189                 vertices.emplace_back(rightX,   bottomY,        0.0f, 1.0f);
190         }
191 };
192
193 // Class that helps create full-screen triangles that overlap each other.
194 // This generator will generate width*height full-screen triangles with decreasing depth from 0.75 to 0.25.
195 class TriangleOverlapGenerator : public TriangleGenerator
196 {
197 private:
198         // Normalized width and height taking into account the framebuffer's width and height are two units (from -1 to 1).
199         deUint32        m_width;
200         deUint32        m_totalPixels;
201         float           m_depthStep;
202
203         static constexpr float kMinDepth        = 0.25f;
204         static constexpr float kMaxDepth        = 0.75f;
205         static constexpr float kDepthRange      = kMaxDepth - kMinDepth;
206
207 public:
208         TriangleOverlapGenerator (deUint32 width, deUint32 height)
209                 : m_width               (width)
210                 , m_totalPixels (width * height)
211                 , m_depthStep   (kDepthRange / static_cast<float>(m_totalPixels))
212         {}
213
214         // Creates full-screen triangle with 2D id (x, y) and decreasing depth with increasing ids.
215         void appendTriangle(deUint32 x, deUint32 y, std::vector<tcu::Vec4>& vertices) override
216         {
217                 const auto pixelId      = static_cast<float>(y * m_width + x);
218                 const auto depth        = kMaxDepth - m_depthStep * pixelId;
219
220                 // Note: clockwise.
221                 vertices.emplace_back(-1.0f,    -1.0f,  depth, 1.0f);
222                 vertices.emplace_back(4.0f,             -1.0f,  depth, 1.0f);
223                 vertices.emplace_back(-1.0f,    4.0f,   depth, 1.0f);
224         }
225 };
226
227 // Class that helps creating a suitable draw info vector.
228 class DrawInfoPacker
229 {
230 private:
231         DrawType                                                m_drawType;
232         tcu::Maybe<VertexOffsetType>    m_offsetType;   // Offset type when m_drawType is DrawType::INDEXED.
233         deUint32                                                m_stride;               // Desired stride. Must be zero or at least as big as the needed VkMultiDraw*InfoExt.
234         deUint32                                                m_extraBytes;   // Used to match the desired stride.
235         de::Random                                              m_random;               // Used to generate random offsets.
236         deUint32                                                m_infoCount;    // How many infos have we appended so far?
237         std::vector<deUint8>                    m_dataVec;              // Data vector in generic form.
238
239         // Are draws indexed and using the offset member of VkMultiDrawIndexedInfoEXT?
240         static bool indexedWithOffset (DrawType drawType, const tcu::Maybe<VertexOffsetType>& offsetType)
241         {
242                 return (drawType == DrawType::INDEXED && *offsetType != VertexOffsetType::CONSTANT_PACK);
243         }
244
245         // Size in bytes for the base structure used with the given draw type.
246         static deUint32 baseSize (DrawType drawType, const tcu::Maybe<VertexOffsetType>& offsetType)
247         {
248                 return static_cast<deUint32>(indexedWithOffset(drawType, offsetType) ? sizeof(VkMultiDrawIndexedInfoEXT) : sizeof(VkMultiDrawInfoEXT));
249         }
250
251         // Number of extra bytes per entry according to the given stride.
252         static deUint32 calcExtraBytes (DrawType drawType, const tcu::Maybe<VertexOffsetType>& offsetType, deUint32 stride)
253         {
254                 // Stride 0 is a special allowed case.
255                 if (stride == 0u)
256                         return 0u;
257
258                 const auto minStride = baseSize(drawType, offsetType);
259                 DE_ASSERT(stride >= minStride);
260                 return (stride - minStride);
261         }
262
263         // Entry size in bytes taking into account the number of extra bytes due to stride.
264         deUint32 entrySize () const
265         {
266                 return baseSize(m_drawType, m_offsetType) + m_extraBytes;
267         }
268
269 public:
270         DrawInfoPacker  (DrawType drawType, const tcu::Maybe<VertexOffsetType>& offsetType, deUint32 stride, deUint32 estimatedInfoCount, deUint32 seed)
271                 : m_drawType    (drawType)
272                 , m_offsetType  (offsetType)
273                 , m_stride              (stride)
274                 , m_extraBytes  (calcExtraBytes(drawType, offsetType, stride))
275                 , m_random              (seed)
276                 , m_infoCount   (0u)
277                 , m_dataVec             ()
278         {
279                 // estimatedInfoCount is used to avoid excessive reallocation.
280                 if (estimatedInfoCount > 0u)
281                         m_dataVec.reserve(estimatedInfoCount * entrySize());
282         }
283
284         void addDrawInfo (deUint32 first, deUint32 count, deInt32 offset)
285         {
286                 std::vector<deUint8> entry(entrySize(), 0);
287
288                 if (indexedWithOffset(m_drawType, m_offsetType))
289                 {
290                         const auto usedOffset = ((*m_offsetType == VertexOffsetType::CONSTANT_RANDOM) ? m_random.getInt32() : offset);
291                         const VkMultiDrawIndexedInfoEXT info = { first, count, usedOffset };
292                         deMemcpy(entry.data(), &info, sizeof(info));
293                 }
294                 else
295                 {
296                         const VkMultiDrawInfoEXT info = { first, count };
297                         deMemcpy(entry.data(), &info, sizeof(info));
298                 }
299
300                 std::copy(begin(entry), end(entry), std::back_inserter(m_dataVec));
301                 ++m_infoCount;
302         }
303
304         deUint32 drawInfoCount () const
305         {
306                 return m_infoCount;
307         }
308
309         const void* drawInfoData () const
310         {
311                 return m_dataVec.data();
312         }
313
314         deUint32 stride () const
315         {
316                 return m_stride;
317         }
318 };
319
320 class MultiDrawTest : public vkt::TestCase
321 {
322 public:
323                                         MultiDrawTest   (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
324         virtual                 ~MultiDrawTest  (void) {}
325
326         void                    initPrograms    (vk::SourceCollections& programCollection) const override;
327         TestInstance*   createInstance  (Context& context) const override;
328         void                    checkSupport    (Context& context) const override;
329
330 private:
331         TestParams              m_params;
332 };
333
334 class MultiDrawInstance : public vkt::TestInstance
335 {
336 public:
337                                                 MultiDrawInstance               (Context& context, const TestParams& params);
338         virtual                         ~MultiDrawInstance              (void) {}
339
340         tcu::TestStatus         iterate                                 (void) override;
341
342 protected:
343         void                            beginSecondaryCmdBuffer (VkCommandBuffer cmdBuffer, VkFormat colorFormat,
344                                                                                                  VkFormat depthStencilFormat, VkRenderingFlagsKHR renderingFlags, deUint32 viewMask) const;
345         void                            preRenderingCommands    (VkCommandBuffer cmdBuffer,
346                                                                                                  VkImage colorImage, const VkImageSubresourceRange colorSubresourceRange,
347                                                                                                  VkImage dsImage, const VkImageSubresourceRange dsSubresourceRange) const;
348         void                            drawCommands                    (VkCommandBuffer cmdBuffer, VkPipeline pipeline,
349                                                                                                  VkBuffer vertexBuffer, VkDeviceSize vertexBufferOffset, deInt32 vertexOffset,
350                                                                                                  VkBuffer indexBuffer, VkDeviceSize indexBufferOffset,
351                                                                                                  bool isMixedMode, const DrawInfoPacker& drawInfos) const;
352
353 private:
354         TestParams                      m_params;
355 };
356
357 MultiDrawTest::MultiDrawTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
358         : vkt::TestCase (testCtx, name, description)
359         , m_params              (params)
360 {}
361
362 TestInstance* MultiDrawTest::createInstance (Context& context) const
363 {
364         return new MultiDrawInstance(context, m_params);
365 }
366
367 void MultiDrawTest::checkSupport (Context& context) const
368 {
369         context.requireDeviceFunctionality("VK_EXT_multi_draw");
370
371         if (m_params.useTessellation)
372                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
373
374         if (m_params.useGeometry)
375                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
376
377         if (m_params.multiview)
378         {
379                 const auto& multiviewFeatures = context.getMultiviewFeatures();
380
381                 if (!multiviewFeatures.multiview)
382                         TCU_THROW(NotSupportedError, "Multiview not supported");
383
384                 if (m_params.useTessellation && !multiviewFeatures.multiviewTessellationShader)
385                         TCU_THROW(NotSupportedError, "Multiview not supported with tesellation shaders");
386
387                 if (m_params.useGeometry && !multiviewFeatures.multiviewGeometryShader)
388                         TCU_THROW(NotSupportedError, "Multiview not supported with geometry shaders");
389         }
390
391         if (m_params.groupParams->useDynamicRendering)
392                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
393 }
394
395 void MultiDrawTest::initPrograms (vk::SourceCollections& programCollection) const
396 {
397         // The general idea behind these tests is to have a 32x32 framebuffer with 1024 pixels and 1024 triangles to draw.
398         //
399         // When using a mosaic mesh, the tests will generally draw a single triangle around the center of each of these pixels. When
400         // using an overlapping mesh, each single triangle will cover the whole framebuffer using a different depth value, and the depth
401         // test will be enabled.
402         //
403         // The color of each triangle will depend on the instance index, the draw index and, when using multiview, the view index. This
404         // way, it's possible to draw those 1024 triangles with a single draw call or to draw each triangle with a separate draw call,
405         // with up to 1024 draw calls. Combinations in between are possible.
406         //
407         // With overlapping meshes, the resulting color buffer will be uniform in color. With mosaic meshes, it depends on the submitted
408         // draw count. In some cases, all pixels will be slightly different in color.
409         //
410         // The color buffer will be cleared to transparent black when beginning the render pass, and in some special cases some or all
411         // pixels will preserve that clear color because they will not be drawn into. This happens, for example, if the instance count
412         // or draw count is zero and in some cases of meshed geometry with stride zero.
413         //
414         // The output color for each pixel will:
415         // - Have the draw index split into the R and G components.
416         // - Have the instance index I stored into the B component as 255-I.
417         //
418         // In addition, the tests will use a depth/stencil buffer. The stencil buffer will be cleared to zero and the depth buffer to an
419         // appropriate initial value (0.0 or 1.0, depending on triangle order). The stencil component will be increased with each draw
420         // on each pixel. This will allow us to verify that not only the last draw for the last instance has set the proper color, but
421         // that all draw operations have taken place.
422
423         // Make sure the blue channel can be calculated without issues.
424         DE_ASSERT(m_params.maxInstanceIndex() <= 255u);
425
426         std::ostringstream vert;
427         vert
428                 << "#version 460\n"
429                 << (m_params.multiview ? "#extension GL_EXT_multiview : enable\n" : "")
430                 << "\n"
431                 << "out gl_PerVertex\n"
432                 << "{\n"
433                 << "    vec4 gl_Position;\n"
434                 << "};\n"
435                 << "\n"
436                 << "layout (location=0) in vec4 inPos;\n"
437                 << "layout (location=0) out uvec4 outColor;\n"
438                 << "\n"
439                 << "void main()\n"
440                 << "{\n"
441                 << "    gl_Position = inPos;\n"
442                 << "    const uint uDrawIndex = uint(gl_DrawID);\n"
443                 << "    outColor.r = ((uDrawIndex >> 8u) & 0xFFu);\n"
444                 << "    outColor.g = ((uDrawIndex      ) & 0xFFu);\n"
445                 << "    outColor.b = 255u - uint(gl_InstanceIndex);\n"
446                 << "    outColor.a = 255u" << (m_params.multiview ? " - uint(gl_ViewIndex)" : "") << ";\n"
447                 << "}\n"
448                 ;
449         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
450
451         std::ostringstream frag;
452         frag
453                 << "#version 460\n"
454                 << "\n"
455                 << "layout (location=0) flat in uvec4 inColor;\n"
456                 << "layout (location=0) out uvec4 outColor;\n"
457                 << "\n"
458                 << "void main ()\n"
459                 << "{\n"
460                 << "    outColor = inColor;\n"
461                 << "}\n"
462                 ;
463         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
464
465         if (m_params.useTessellation)
466         {
467                 std::ostringstream tesc;
468                 tesc
469                         << "#version 460\n"
470                         << "\n"
471                         << "layout (vertices=3) out;\n"
472                         << "in gl_PerVertex\n"
473                         << "{\n"
474                         << "    vec4 gl_Position;\n"
475                         << "} gl_in[gl_MaxPatchVertices];\n"
476                         << "out gl_PerVertex\n"
477                         << "{\n"
478                         << "    vec4 gl_Position;\n"
479                         << "} gl_out[];\n"
480                         << "\n"
481                         << "layout (location=0) in uvec4 inColor[gl_MaxPatchVertices];\n"
482                         << "layout (location=0) out uvec4 outColor[];\n"
483                         << "\n"
484                         << "void main (void)\n"
485                         << "{\n"
486                         << "    gl_TessLevelInner[0] = 1.0;\n"
487                         << "    gl_TessLevelInner[1] = 1.0;\n"
488                         << "    gl_TessLevelOuter[0] = 1.0;\n"
489                         << "    gl_TessLevelOuter[1] = 1.0;\n"
490                         << "    gl_TessLevelOuter[2] = 1.0;\n"
491                         << "    gl_TessLevelOuter[3] = 1.0;\n"
492                         << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
493                         << "    outColor[gl_InvocationID] = inColor[gl_InvocationID];\n"
494                         << "}\n"
495                         ;
496                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
497
498                 std::ostringstream tese;
499                 tese
500                         << "#version 460\n"
501                         << "\n"
502                         << "layout (triangles, fractional_odd_spacing, cw) in;\n"
503                         << "in gl_PerVertex\n"
504                         << "{\n"
505                         << "    vec4 gl_Position;\n"
506                         << "} gl_in[gl_MaxPatchVertices];\n"
507                         << "out gl_PerVertex\n"
508                         << "{\n"
509                         << "    vec4 gl_Position;\n"
510                         << "};\n"
511                         << "\n"
512                         << "layout (location=0) in uvec4 inColor[gl_MaxPatchVertices];\n"
513                         << "layout (location=0) out uvec4 outColor;\n"
514                         << "\n"
515                         << "void main (void)\n"
516                         << "{\n"
517                         << "    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
518                         << "                  (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
519                         << "                  (gl_TessCoord.z * gl_in[2].gl_Position);\n"
520                         << "    outColor = inColor[0];\n"
521                         << "}\n"
522                         ;
523                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
524         }
525
526         if (m_params.useGeometry)
527         {
528                 std::ostringstream geom;
529                 geom
530                         << "#version 460\n"
531                         << "\n"
532                         << "layout (triangles) in;\n"
533                         << "layout (triangle_strip, max_vertices=3) out;\n"
534                         << "in gl_PerVertex\n"
535                         << "{\n"
536                         << "    vec4 gl_Position;\n"
537                         << "} gl_in[3];\n"
538                         << "out gl_PerVertex\n"
539                         << "{\n"
540                         << "    vec4 gl_Position;\n"
541                         << "};\n"
542                         << "\n"
543                         << "layout (location=0) in uvec4 inColor[3];\n"
544                         << "layout (location=0) out uvec4 outColor;\n"
545                         << "\n"
546                         << "void main ()\n"
547                         << "{\n"
548                         << "    gl_Position = gl_in[0].gl_Position; outColor = inColor[0]; EmitVertex();\n"
549                         << "    gl_Position = gl_in[1].gl_Position; outColor = inColor[1]; EmitVertex();\n"
550                         << "    gl_Position = gl_in[2].gl_Position; outColor = inColor[2]; EmitVertex();\n"
551                         << "}\n"
552                         ;
553                 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
554         }
555 }
556
557 MultiDrawInstance::MultiDrawInstance (Context& context, const TestParams& params)
558         : vkt::TestInstance     (context)
559         , m_params                      (params)
560 {}
561
562 void appendPaddingVertices (std::vector<tcu::Vec4>& vertices, deUint32 count)
563 {
564         for (deUint32 i = 0u; i < count; ++i)
565                 vertices.emplace_back(0.0f, 0.0f, 0.0f, 1.0f);
566 }
567
568 // Creates a render pass with multiple subpasses, one per layer.
569 Move<VkRenderPass> makeMultidrawRenderPass (const DeviceInterface&      vk,
570                                                                                         VkDevice                                device,
571                                                                                         VkFormat                                colorFormat,
572                                                                                         VkFormat                                depthStencilFormat,
573                                                                                         deUint32                                layerCount)
574 {
575         const VkAttachmentDescription colorAttachmentDescription =
576         {
577                 0u,                                                                                     // VkAttachmentDescriptionFlags    flags
578                 colorFormat,                                                            // VkFormat                        format
579                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits           samples
580                 VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp              loadOp
581                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp             storeOp
582                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp              stencilLoadOp
583                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp             stencilStoreOp
584                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                   initialLayout
585                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                   finalLayout
586         };
587
588         const VkAttachmentDescription depthStencilAttachmentDescription =
589         {
590                 0u,                                                                                                     // VkAttachmentDescriptionFlags    flags
591                 depthStencilFormat,                                                                     // VkFormat                        format
592                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits           samples
593                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp              loadOp
594                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp             storeOp
595                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp              stencilLoadOp
596                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp             stencilStoreOp
597                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                   initialLayout
598                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                   finalLayout
599         };
600
601         const std::vector<VkAttachmentDescription>      attachmentDescriptions          = { colorAttachmentDescription, depthStencilAttachmentDescription };
602         const VkAttachmentReference                                     colorAttachmentRef                      = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
603         const VkAttachmentReference                                     depthStencilAttachmentRef       = makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
604
605         const VkSubpassDescription subpassDescription =
606         {
607                 0u,                                                                     // VkSubpassDescriptionFlags       flags
608                 VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint             pipelineBindPoint
609                 0u,                                                                     // deUint32                        inputAttachmentCount
610                 nullptr,                                                        // const VkAttachmentReference*    pInputAttachments
611                 1u,                                                                     // deUint32                        colorAttachmentCount
612                 &colorAttachmentRef,                            // const VkAttachmentReference*    pColorAttachments
613                 nullptr,                                                        // const VkAttachmentReference*    pResolveAttachments
614                 &depthStencilAttachmentRef,                     // const VkAttachmentReference*    pDepthStencilAttachment
615                 0u,                                                                     // deUint32                        preserveAttachmentCount
616                 nullptr                                                         // const deUint32*                 pPreserveAttachments
617         };
618
619         std::vector<VkSubpassDescription> subpassDescriptions;
620
621         subpassDescriptions.reserve(layerCount);
622         for (deUint32 subpassIdx = 0u; subpassIdx < layerCount; ++subpassIdx)
623                 subpassDescriptions.push_back(subpassDescription);
624
625         using MultiviewInfoPtr = de::MovePtr<VkRenderPassMultiviewCreateInfo>;
626
627         MultiviewInfoPtr multiviewCreateInfo;
628         std::vector<deUint32> viewMasks;
629
630         if (layerCount > 1u)
631         {
632                 multiviewCreateInfo             = MultiviewInfoPtr(new VkRenderPassMultiviewCreateInfo);
633                 *multiviewCreateInfo    = initVulkanStructure();
634
635                 viewMasks.resize(subpassDescriptions.size());
636                 for (deUint32 subpassIdx = 0u; subpassIdx < static_cast<deUint32>(viewMasks.size()); ++subpassIdx)
637                         viewMasks[subpassIdx] = (1u << subpassIdx);
638
639                 multiviewCreateInfo->subpassCount       = static_cast<deUint32>(viewMasks.size());
640                 multiviewCreateInfo->pViewMasks         = de::dataOrNull(viewMasks);
641         }
642
643         // Dependencies between subpasses for color and depth/stencil read/writes.
644         std::vector<VkSubpassDependency> dependencies;
645         if (layerCount > 1u)
646                 dependencies.reserve((layerCount - 1u) * 2u);
647
648         const auto fragmentTestStages   = (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
649         const auto dsWrites                             = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
650         const auto dsReadWrites                 = (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
651         const auto colorStage                   = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
652         const auto colorWrites                  = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
653         const auto colorReadWrites              = (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
654
655         for (deUint32 subpassIdx = 1u; subpassIdx < layerCount; ++subpassIdx)
656         {
657                 const auto prev = subpassIdx - 1u;
658
659                 const VkSubpassDependency dsDep =
660                 {
661                         prev,                                                   //      deUint32                                srcSubpass;
662                         subpassIdx,                                             //      deUint32                                dstSubpass;
663                         fragmentTestStages,                             //      VkPipelineStageFlags    srcStageMask;
664                         fragmentTestStages,                             //      VkPipelineStageFlags    dstStageMask;
665                         dsWrites,                                               //      VkAccessFlags                   srcAccessMask;
666                         dsReadWrites,                                   //      VkAccessFlags                   dstAccessMask;
667                         VK_DEPENDENCY_BY_REGION_BIT,    //      VkDependencyFlags               dependencyFlags;
668                 };
669                 dependencies.push_back(dsDep);
670
671                 const VkSubpassDependency colorDep =
672                 {
673                         prev,                                                   //      deUint32                                srcSubpass;
674                         subpassIdx,                                             //      deUint32                                dstSubpass;
675                         colorStage,                                             //      VkPipelineStageFlags    srcStageMask;
676                         colorStage,                                             //      VkPipelineStageFlags    dstStageMask;
677                         colorWrites,                                    //      VkAccessFlags                   srcAccessMask;
678                         colorReadWrites,                                //      VkAccessFlags                   dstAccessMask;
679                         VK_DEPENDENCY_BY_REGION_BIT,    //      VkDependencyFlags               dependencyFlags;
680                 };
681                 dependencies.push_back(colorDep);
682         }
683
684         const VkRenderPassCreateInfo renderPassInfo =
685         {
686                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                   sType
687                 multiviewCreateInfo.get(),                                                              // const void*                       pNext
688                 0u,                                                                                                             // VkRenderPassCreateFlags           flags
689                 static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                          attachmentCount
690                 de::dataOrNull(attachmentDescriptions),                                 // const VkAttachmentDescription*    pAttachments
691                 static_cast<deUint32>(subpassDescriptions.size()),              // deUint32                          subpassCount
692                 de::dataOrNull(subpassDescriptions),                                    // const VkSubpassDescription*       pSubpasses
693                 static_cast<deUint32>(dependencies.size()),                             // deUint32                          dependencyCount
694                 de::dataOrNull(dependencies),                                                   // const VkSubpassDependency*        pDependencies
695         };
696
697         return createRenderPass(vk, device, &renderPassInfo, nullptr);
698 }
699
700 void MultiDrawInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
701                                                                                                 VkFormat depthStencilFormat, VkRenderingFlagsKHR renderingFlags, deUint32 viewMask) const
702 {
703         VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
704         {
705                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,                // VkStructureType                                      sType;
706                 DE_NULL,                                                                                                                                // const void*                                          pNext;
707                 renderingFlags,                                                                                                                 // VkRenderingFlagsKHR                          flags;
708                 viewMask,                                                                                                                               // uint32_t                                                     viewMask;
709                 1u,                                                                                                                                             // uint32_t                                                     colorAttachmentCount;
710                 &colorFormat,                                                                                                                   // const VkFormat*                                      pColorAttachmentFormats;
711                 depthStencilFormat,                                                                                                             // VkFormat                                                     depthAttachmentFormat;
712                 depthStencilFormat,                                                                                                             // VkFormat                                                     stencilAttachmentFormat;
713                 VK_SAMPLE_COUNT_1_BIT,                                                                                                  // VkSampleCountFlagBits                        rasterizationSamples;
714         };
715
716         const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
717
718         VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
719         if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
720                 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
721
722         const VkCommandBufferBeginInfo commandBufBeginParams
723         {
724                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                                                    // VkStructureType                                      sType;
725                 DE_NULL,                                                                                                                                // const void*                                          pNext;
726                 usageFlags,                                                                                                                             // VkCommandBufferUsageFlags            flags;
727                 &bufferInheritanceInfo
728         };
729
730         const DeviceInterface& vk = m_context.getDeviceInterface();
731         VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
732 }
733
734 void MultiDrawInstance::preRenderingCommands(VkCommandBuffer cmdBuffer,
735                                                                                          VkImage colorImage, const VkImageSubresourceRange colorSubresourceRange,
736                                                                                          VkImage dsImage, const VkImageSubresourceRange dsSubresourceRange) const
737 {
738         const auto& vk = m_context.getDeviceInterface();
739
740         // Transition color and depth stencil attachment to the proper initial layout for dynamic rendering
741         const auto colorPreBarrier = makeImageMemoryBarrier(
742                 0u,
743                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
744                 VK_IMAGE_LAYOUT_UNDEFINED,
745                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
746                 colorImage, colorSubresourceRange);
747
748         vk.cmdPipelineBarrier(
749                 cmdBuffer,
750                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
751                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
752                 0u, 0u, nullptr, 0u, nullptr, 1u, &colorPreBarrier);
753
754         const auto dsPreBarrier = makeImageMemoryBarrier(
755                 0u,
756                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
757                 VK_IMAGE_LAYOUT_UNDEFINED,
758                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
759                 dsImage, dsSubresourceRange);
760
761         vk.cmdPipelineBarrier(
762                 cmdBuffer,
763                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
764                 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT),
765                 0u, 0u, nullptr, 0u, nullptr, 1u, &dsPreBarrier);
766 }
767
768 void MultiDrawInstance::drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline,
769                                                                          VkBuffer vertexBuffer, VkDeviceSize vertexBufferOffset, deInt32 vertexOffset,
770                                                                          VkBuffer indexBuffer, VkDeviceSize indexBufferOffset,
771                                                                          bool isMixedMode, const DrawInfoPacker& drawInfos) const
772 {
773         const auto& vk = m_context.getDeviceInterface();
774
775         vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
776         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
777
778         if (indexBuffer == DE_NULL)
779         {
780                 const auto drawInfoPtr = reinterpret_cast<const VkMultiDrawInfoEXT*>(drawInfos.drawInfoData());
781                 vk.cmdDrawMultiEXT(cmdBuffer, drawInfos.drawInfoCount(), drawInfoPtr, m_params.instanceCount, m_params.firstInstance, drawInfos.stride());
782         }
783         else
784         {
785                 vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, indexBufferOffset, VK_INDEX_TYPE_UINT32);
786
787                 const auto drawInfoPtr = reinterpret_cast<const VkMultiDrawIndexedInfoEXT*>(drawInfos.drawInfoData());
788                 const auto offsetPtr = (isMixedMode ? nullptr : &vertexOffset);
789                 vk.cmdDrawMultiIndexedEXT(cmdBuffer, drawInfos.drawInfoCount(), drawInfoPtr, m_params.instanceCount, m_params.firstInstance, drawInfos.stride(), offsetPtr);
790         }
791 }
792
793 tcu::TestStatus MultiDrawInstance::iterate (void)
794 {
795         const auto&     vki                             = m_context.getInstanceInterface();
796         const auto      physDev                 = m_context.getPhysicalDevice();
797         const auto&     vkd                             = m_context.getDeviceInterface();
798         const auto      device                  = m_context.getDevice();
799         auto&           alloc                   = m_context.getDefaultAllocator();
800         const auto      queue                   = m_context.getUniversalQueue();
801         const auto      qIndex                  = m_context.getUniversalQueueFamilyIndex();
802
803         const auto      colorFormat             = getColorFormat();
804         const auto      dsFormat                = chooseDepthStencilFormat(vki, physDev);
805         const auto      tcuColorFormat  = mapVkFormat(colorFormat);
806         const auto      triangleCount   = getTriangleCount();
807         const auto      imageDim                = static_cast<deUint32>(deSqrt(static_cast<double>(triangleCount)));
808         const auto      imageExtent             = makeExtent3D(imageDim, imageDim, 1u);
809         const auto      imageLayers             = (m_params.multiview ? 2u : 1u);
810         const auto      imageViewType   = ((imageLayers > 1u) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
811         const auto      colorUsage              = (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
812         const auto      dsUsage                 = (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
813         const auto      pixelCount              = imageExtent.width * imageExtent.height;
814         const auto      vertexCount             = pixelCount * 3u; // Triangle list.
815         const auto      isIndexed               = (m_params.drawType == DrawType::INDEXED);
816         const auto      isMixedMode             = (isIndexed && m_params.vertexOffset && m_params.vertexOffset->offsetType == VertexOffsetType::MIXED);
817         const auto      extraVertices   = (m_params.vertexOffset ? m_params.vertexOffset->offset : 0u);
818         const auto      isMosaic                = (m_params.meshType == MeshType::MOSAIC);
819
820         // Make sure we're providing a vertex offset for indexed cases.
821         DE_ASSERT(!isIndexed || static_cast<bool>(m_params.vertexOffset));
822
823         // Make sure overlapping draws use a single instance.
824         DE_ASSERT(isMosaic || m_params.instanceCount <= 1u);
825
826         // Color buffer.
827         const VkImageCreateInfo imageCreateInfo =
828         {
829                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    //      VkStructureType                 sType;
830                 nullptr,                                                                //      const void*                             pNext;
831                 0u,                                                                             //      VkImageCreateFlags              flags;
832                 VK_IMAGE_TYPE_2D,                                               //      VkImageType                             imageType;
833                 colorFormat,                                                    //      VkFormat                                format;
834                 imageExtent,                                                    //      VkExtent3D                              extent;
835                 1u,                                                                             //      deUint32                                mipLevels;
836                 imageLayers,                                                    //      deUint32                                arrayLayers;
837                 VK_SAMPLE_COUNT_1_BIT,                                  //      VkSampleCountFlagBits   samples;
838                 VK_IMAGE_TILING_OPTIMAL,                                //      VkImageTiling                   tiling;
839                 colorUsage,                                                             //      VkImageUsageFlags               usage;
840                 VK_SHARING_MODE_EXCLUSIVE,                              //      VkSharingMode                   sharingMode;
841                 0u,                                                                             //      deUint32                                queueFamilyIndexCount;
842                 nullptr,                                                                //      const deUint32*                 pQueueFamilyIndices;
843                 VK_IMAGE_LAYOUT_UNDEFINED,                              //      VkImageLayout                   initialLayout;
844         };
845
846         ImageWithMemory colorBuffer                             (vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any);
847         const auto              colorSubresourceRange   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, imageLayers);
848         const auto              colorBufferView                 = makeImageView(vkd, device, colorBuffer.get(), imageViewType, colorFormat, colorSubresourceRange);
849
850         // Depth/stencil buffer.
851         const VkImageCreateInfo dsCreateInfo =
852         {
853                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    //      VkStructureType                 sType;
854                 nullptr,                                                                //      const void*                             pNext;
855                 0u,                                                                             //      VkImageCreateFlags              flags;
856                 VK_IMAGE_TYPE_2D,                                               //      VkImageType                             imageType;
857                 dsFormat,                                                               //      VkFormat                                format;
858                 imageExtent,                                                    //      VkExtent3D                              extent;
859                 1u,                                                                             //      deUint32                                mipLevels;
860                 imageLayers,                                                    //      deUint32                                arrayLayers;
861                 VK_SAMPLE_COUNT_1_BIT,                                  //      VkSampleCountFlagBits   samples;
862                 VK_IMAGE_TILING_OPTIMAL,                                //      VkImageTiling                   tiling;
863                 dsUsage,                                                                //      VkImageUsageFlags               usage;
864                 VK_SHARING_MODE_EXCLUSIVE,                              //      VkSharingMode                   sharingMode;
865                 0u,                                                                             //      deUint32                                queueFamilyIndexCount;
866                 nullptr,                                                                //      const deUint32*                 pQueueFamilyIndices;
867                 VK_IMAGE_LAYOUT_UNDEFINED,                              //      VkImageLayout                   initialLayout;
868         };
869
870         ImageWithMemory dsBuffer                        (vkd, device, alloc, dsCreateInfo, MemoryRequirement::Any);
871         const auto              dsSubresourceRange      = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, imageLayers);
872         const auto              dsBufferView            = makeImageView(vkd, device, dsBuffer.get(), imageViewType, dsFormat, dsSubresourceRange);
873
874         // Output buffers to verify attachments.
875         using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
876
877         // Buffers to read color attachment.
878         const auto outputBufferSize = pixelCount * static_cast<VkDeviceSize>(tcu::getPixelSize(tcuColorFormat));
879         const auto bufferCreateInfo = makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
880
881         std::vector<BufferWithMemoryPtr> outputBuffers;
882         for (deUint32 i = 0u; i < imageLayers; ++i)
883                 outputBuffers.push_back(BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible)));
884
885         // Buffer to read depth/stencil attachment. Note: this supposes we'll only copy the stencil aspect. See below.
886         const auto                      tcuStencilFmt                   = mapVkFormat(getStencilVerificationFormat());
887         const auto                      stencilOutBufferSize    = pixelCount * static_cast<VkDeviceSize>(tcu::getPixelSize(tcuStencilFmt));
888         const auto                      stencilOutCreateInfo    = makeBufferCreateInfo(stencilOutBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
889
890         std::vector<BufferWithMemoryPtr> stencilOutBuffers;
891         for (deUint32 i = 0u; i < imageLayers; ++i)
892                 stencilOutBuffers.push_back(BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, stencilOutCreateInfo, MemoryRequirement::HostVisible)));
893
894         // Shaders.
895         const auto                              vertModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
896         const auto                              fragModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
897         Move<VkShaderModule>    tescModule;
898         Move<VkShaderModule>    teseModule;
899         Move<VkShaderModule>    geomModule;
900
901         if (m_params.useGeometry)
902                 geomModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("geom"), 0u);
903
904         if (m_params.useTessellation)
905         {
906                 tescModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("tesc"), 0u);
907                 teseModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("tese"), 0u);
908         }
909
910         DescriptorSetLayoutBuilder      layoutBuilder;
911         const auto                                      descriptorSetLayout     = layoutBuilder.build(vkd, device);
912         const auto                                      pipelineLayout          = makePipelineLayout(vkd, device, descriptorSetLayout.get());
913
914         Move<VkRenderPass>                      renderPass;
915         Move<VkFramebuffer>                     framebuffer;
916
917         // Render pass and Framebuffer (note layers is always 1 as required by the spec).
918         if (!m_params.groupParams->useDynamicRendering)
919         {
920                 renderPass = makeMultidrawRenderPass(vkd, device, colorFormat, dsFormat, imageLayers);
921                 const std::vector<VkImageView> attachments { colorBufferView.get(), dsBufferView.get() };
922                 framebuffer = makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(attachments.size()), de::dataOrNull(attachments), imageExtent.width, imageExtent.height, 1u);
923         }
924
925         // Viewports and scissors.
926         const auto                                              viewport        = makeViewport(imageExtent);
927         const std::vector<VkViewport>   viewports       (1u, viewport);
928         const auto                                              scissor         = makeRect2D(imageExtent);
929         const std::vector<VkRect2D>             scissors        (1u, scissor);
930
931         // Indexed draws will have triangle vertices in reverse order. See index buffer creation below.
932         const auto                                                                              frontFace                       = (isIndexed ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE);
933         const VkPipelineRasterizationStateCreateInfo    rasterizationInfo       =
934         {
935                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     //      VkStructureType                                                 sType;
936                 nullptr,                                                                                                        //      const void*                                                             pNext;
937                 0u,                                                                                                                     //      VkPipelineRasterizationStateCreateFlags flags;
938                 VK_FALSE,                                                                                                       //      VkBool32                                                                depthClampEnable;
939                 VK_FALSE,                                                                                                       //      VkBool32                                                                rasterizerDiscardEnable;
940                 VK_POLYGON_MODE_FILL,                                                                           //      VkPolygonMode                                                   polygonMode;
941                 VK_CULL_MODE_BACK_BIT,                                                                          //      VkCullModeFlags                                                 cullMode;
942                 frontFace,                                                                                                      //      VkFrontFace                                                             frontFace;
943                 VK_FALSE,                                                                                                       //      VkBool32                                                                depthBiasEnable;
944                 0.0f,                                                                                                           //      float                                                                   depthBiasConstantFactor;
945                 0.0f,                                                                                                           //      float                                                                   depthBiasClamp;
946                 0.0f,                                                                                                           //      float                                                                   depthBiasSlopeFactor;
947                 1.0f,                                                                                                           //      float                                                                   lineWidth;
948         };
949
950         const auto frontStencilState    = makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
951         const auto backStencilState             = makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0xFFu, 0xFFu, 0u);
952         const auto depthTestEnable              = (isMosaic ? VK_FALSE : VK_TRUE);
953         const auto depthWriteEnable             = depthTestEnable;
954         const auto depthCompareOp               = (isMosaic ? VK_COMPARE_OP_ALWAYS : (isIndexed ? VK_COMPARE_OP_GREATER : VK_COMPARE_OP_LESS));
955
956         const VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
957         {
958                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             //      VkStructureType                                                 sType;
959                 nullptr,                                                                                                                //      const void*                                                             pNext;
960                 0u,                                                                                                                             //      VkPipelineDepthStencilStateCreateFlags  flags;
961                 depthTestEnable,                                                                                                //      VkBool32                                                                depthTestEnable;
962                 depthWriteEnable,                                                                                               //      VkBool32                                                                depthWriteEnable;
963                 depthCompareOp,                                                                                                 //      VkCompareOp                                                             depthCompareOp;
964                 VK_FALSE,                                                                                                               //      VkBool32                                                                depthBoundsTestEnable;
965                 VK_TRUE,                                                                                                                //      VkBool32                                                                stencilTestEnable;
966                 frontStencilState,                                                                                              //      VkStencilOpState                                                front;
967                 backStencilState,                                                                                               //      VkStencilOpState                                                back;
968                 0.0f,                                                                                                                   //      float                                                                   minDepthBounds;
969                 1.0f,                                                                                                                   //      float                                                                   maxDepthBounds;
970         };
971
972         vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
973         {
974                 vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
975                 DE_NULL,
976                 0u,
977                 1u,
978                 &colorFormat,
979                 dsFormat,
980                 dsFormat
981         };
982
983         vk::VkPipelineRenderingCreateInfoKHR* nextPtr = nullptr;
984         if (m_params.groupParams->useDynamicRendering)
985                 nextPtr = &renderingCreateInfo;
986
987         const auto primitiveTopology    = (m_params.useTessellation ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
988         const auto patchControlPoints   = (m_params.useTessellation ? 3u : 0u);
989
990         // Pipelines.
991         std::vector<Move<VkPipeline>> pipelines;
992         pipelines.reserve(imageLayers);
993         for (deUint32 subpassIdx = 0u; subpassIdx < imageLayers; ++subpassIdx)
994         {
995                 renderingCreateInfo.viewMask = m_params.multiview ? (1u << subpassIdx) : 0u;
996                 pipelines.emplace_back(makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
997                         vertModule.get(), tescModule.get(), teseModule.get(), geomModule.get(), fragModule.get(),
998                         renderPass.get(), viewports, scissors, primitiveTopology, m_params.groupParams->useDynamicRendering ? 0u : subpassIdx, patchControlPoints,
999                         nullptr/*vertexInputStateCreateInfo*/, &rasterizationInfo, nullptr/*multisampleStateCreateInfo*/, &depthStencilInfo,
1000                         nullptr/*colorBlendStateCreateInfo*/, nullptr/*dynamicStateCreateInfo*/, nextPtr));
1001         }
1002
1003         // Command pool and buffer.
1004         const auto                                                              cmdPool                 = makeCommandPool(vkd, device, qIndex);
1005         Move<VkCommandBuffer>                                   cmdBufferPtr    = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1006         VkCommandBuffer                                                 cmdBuffer               = cmdBufferPtr.get();
1007         std::vector<Move<VkCommandBuffer> >             secCmdBuffers;
1008
1009         // Create vertex buffer.
1010         std::vector<tcu::Vec4> triangleVertices;
1011         triangleVertices.reserve(vertexCount + extraVertices);
1012
1013         // Vertex count per draw call.
1014         const bool atLeastOneDraw       = (m_params.drawCount > 0u);
1015         const bool moreThanOneDraw      = (m_params.drawCount > 1u);
1016         const auto trianglesPerDraw     = (atLeastOneDraw ? pixelCount / m_params.drawCount : 0u);
1017         const auto verticesPerDraw      = trianglesPerDraw * 3u;
1018
1019         if (atLeastOneDraw)
1020                 DE_ASSERT(pixelCount % m_params.drawCount == 0u);
1021
1022         {
1023                 using TriangleGeneratorPtr = de::MovePtr<TriangleGenerator>;
1024                 TriangleGeneratorPtr triangleGen;
1025
1026                 if (m_params.meshType == MeshType::MOSAIC)
1027                         triangleGen = TriangleGeneratorPtr(new TriangleMosaicGenerator(imageExtent.width, imageExtent.height));
1028                 else if (m_params.meshType == MeshType::OVERLAPPING)
1029                         triangleGen = TriangleGeneratorPtr(new TriangleOverlapGenerator(imageExtent.width, imageExtent.height));
1030                 else
1031                         DE_ASSERT(false);
1032
1033                 // When applying a vertex offset in nonmixed modes, there will be a few extra vertices at the start of the vertex buffer.
1034                 if (isIndexed && !isMixedMode)
1035                         appendPaddingVertices(triangleVertices, extraVertices);
1036
1037                 for (deUint32 y = 0u; y < imageExtent.height; ++y)
1038                 for (deUint32 x = 0u; x < imageExtent.width; ++x)
1039                 {
1040                         // When applying a vertex offset in mixed mode, there will be some extra padding between the triangles for the first
1041                         // block and the rest, so that the vertex offset will not be constant in all draw info structures. This way, the first
1042                         // triangles will always have offset zero, and the number of them depends on the given draw count.
1043                         const auto pixelIndex = y * imageExtent.width + x;
1044                         if (isIndexed && isMixedMode && moreThanOneDraw && pixelIndex == trianglesPerDraw)
1045                                 appendPaddingVertices(triangleVertices, extraVertices);
1046
1047                         triangleGen->appendTriangle(x, y, triangleVertices);
1048                 }
1049         }
1050
1051         const auto                      vertexBufferSize        = static_cast<VkDeviceSize>(de::dataSize(triangleVertices));
1052         const auto                      vertexBufferInfo        = makeBufferCreateInfo(vertexBufferSize, (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1053         BufferWithMemory        vertexBuffer            (vkd, device, alloc, vertexBufferInfo, MemoryRequirement::HostVisible);
1054         auto&                           vertexBufferAlloc       = vertexBuffer.getAllocation();
1055         const auto                      vertexBufferOffset      = vertexBufferAlloc.getOffset();
1056         void*                           vertexBufferData        = vertexBufferAlloc.getHostPtr();
1057
1058         deMemcpy(vertexBufferData, triangleVertices.data(), de::dataSize(triangleVertices));
1059         flushAlloc(vkd, device, vertexBufferAlloc);
1060
1061         // Index buffer if needed.
1062         de::MovePtr<BufferWithMemory>   indexBuffer;
1063         VkDeviceSize                                    indexBufferOffset = 0ull;
1064         VkBuffer                                                indexBufferHandle = DE_NULL;
1065
1066         if (isIndexed)
1067         {
1068                 // Indices will be given in reverse order, so they effectively also make the triangles have reverse winding order.
1069                 std::vector<deUint32> indices;
1070                 indices.reserve(vertexCount);
1071                 for (deUint32 i = 0u; i < vertexCount; ++i)
1072                         indices.push_back(vertexCount - i - 1u);
1073
1074                 const auto      indexBufferSize         = static_cast<VkDeviceSize>(de::dataSize(indices));
1075                 const auto      indexBufferInfo         = makeBufferCreateInfo(indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
1076                                         indexBuffer                     = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, alloc, indexBufferInfo, MemoryRequirement::HostVisible));
1077                 auto&           indexBufferAlloc        = indexBuffer->getAllocation();
1078                                         indexBufferOffset       = indexBufferAlloc.getOffset();
1079                 void*           indexBufferData         = indexBufferAlloc.getHostPtr();
1080
1081                 deMemcpy(indexBufferData, indices.data(), de::dataSize(indices));
1082                 flushAlloc(vkd, device, indexBufferAlloc);
1083                 indexBufferHandle = indexBuffer->get();
1084         }
1085
1086         // Prepare draw information.
1087         const auto offsetType   = (m_params.vertexOffset ? tcu::just(m_params.vertexOffset->offsetType) : tcu::Nothing);
1088         const auto vertexOffset = static_cast<deInt32>(extraVertices);
1089
1090         DrawInfoPacker drawInfos(m_params.drawType, offsetType, m_params.stride, m_params.drawCount, m_params.seed);
1091
1092         if (m_params.drawCount > 0u)
1093         {
1094                 deUint32 vertexIndex = 0u;
1095                 for (deUint32 drawIdx = 0u; drawIdx < m_params.drawCount; ++drawIdx)
1096                 {
1097                         // For indexed draws in mixed offset mode, taking into account vertex indices have been stored in reversed order and
1098                         // there may be a padding in the vertex buffer after the first verticesPerDraw vertices, we need to use offset 0 in the
1099                         // last draw call. That draw will contain the indices for the first verticesPerDraw vertices, which are stored without
1100                         // any offset, while other draw calls will use indices which are off by extraVertices vertices. This will make sure not
1101                         // every draw call will use the same offset and the implementation handles that.
1102                         const auto drawOffset = ((isIndexed && (!isMixedMode || (moreThanOneDraw && drawIdx < m_params.drawCount - 1u))) ? vertexOffset : 0);
1103                         drawInfos.addDrawInfo(vertexIndex, verticesPerDraw, drawOffset);
1104                         vertexIndex += verticesPerDraw;
1105                 }
1106         }
1107
1108         std::vector<VkClearValue> clearValues;
1109         clearValues.reserve(2u);
1110         clearValues.push_back(makeClearValueColorU32(0u, 0u, 0u, 0u));
1111         clearValues.push_back(makeClearValueDepthStencil(((isMosaic || isIndexed) ? 0.0f : 1.0f), 0u));
1112
1113         if (m_params.groupParams->useSecondaryCmdBuffer)
1114         {
1115                 secCmdBuffers.resize(imageLayers);
1116                 for (deUint32 layerIdx = 0u; layerIdx < imageLayers; ++layerIdx)
1117                 {
1118                         secCmdBuffers[layerIdx]                 = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1119                         VkCommandBuffer secCmdBuffer    = *secCmdBuffers[layerIdx];
1120                         const deUint32  viewMask                = m_params.multiview ? (1u << layerIdx) : 0u;
1121
1122                         // record secondary command buffer
1123                         if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1124                         {
1125                                 beginSecondaryCmdBuffer(secCmdBuffer, colorFormat, dsFormat, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, viewMask);
1126                                 beginRendering(vkd, secCmdBuffer, *colorBufferView, *dsBufferView, true, scissor, clearValues[0], clearValues[1],
1127                                                            vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1128                                                            VK_ATTACHMENT_LOAD_OP_CLEAR, 0, imageLayers, viewMask);
1129                         }
1130                         else
1131                                 beginSecondaryCmdBuffer(secCmdBuffer, colorFormat, dsFormat, 0u, viewMask);
1132
1133                         drawCommands(secCmdBuffer, pipelines[layerIdx].get(), vertexBuffer.get(), vertexBufferOffset, vertexOffset,
1134                                                  indexBufferHandle, indexBufferOffset, isMixedMode, drawInfos);
1135
1136                         if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1137                                 endRendering(vkd, secCmdBuffer);
1138
1139                         endCommandBuffer(vkd, secCmdBuffer);
1140                 }
1141
1142                 // record primary command buffer
1143                 beginCommandBuffer(vkd, cmdBuffer, 0u);
1144                 preRenderingCommands(cmdBuffer, *colorBuffer, colorSubresourceRange, *dsBuffer, dsSubresourceRange);
1145
1146                 for (deUint32 layerIdx = 0u; layerIdx < imageLayers; ++layerIdx)
1147                 {
1148                         if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1149                         {
1150                                 beginRendering(vkd, cmdBuffer, *colorBufferView, *dsBufferView, true, scissor, clearValues[0], clearValues[1],
1151                                                            vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1152                                                            VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, imageLayers,
1153                                                            m_params.multiview ? (1u << layerIdx) : 0u);
1154                         }
1155
1156                         vkd.cmdExecuteCommands(cmdBuffer, 1u, &*secCmdBuffers[layerIdx]);
1157
1158                         if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1159                                 endRendering(vkd, cmdBuffer);
1160                 }
1161         }
1162         else
1163         {
1164                 beginCommandBuffer(vkd, cmdBuffer);
1165
1166                 if (m_params.groupParams->useDynamicRendering)
1167                         preRenderingCommands(cmdBuffer, *colorBuffer, colorSubresourceRange, *dsBuffer, dsSubresourceRange);
1168                 else
1169                         beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissor, static_cast<deUint32>(clearValues.size()), de::dataOrNull(clearValues));
1170
1171                 for (deUint32 layerIdx = 0u; layerIdx < imageLayers; ++layerIdx)
1172                 {
1173                         if (m_params.groupParams->useDynamicRendering)
1174                                 beginRendering(vkd, cmdBuffer, *colorBufferView, *dsBufferView, true, scissor, clearValues[0], clearValues[1],
1175                                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1176                                         VK_ATTACHMENT_LOAD_OP_CLEAR, 0, imageLayers, m_params.multiview ? (1u << layerIdx) : 0u);
1177                         else if (layerIdx > 0u)
1178                                 vkd.cmdNextSubpass(cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1179
1180                         drawCommands(cmdBuffer, pipelines[layerIdx].get(), vertexBuffer.get(), vertexBufferOffset, vertexOffset,
1181                                                  indexBufferHandle, indexBufferOffset, isMixedMode, drawInfos);
1182
1183                         if (m_params.groupParams->useDynamicRendering)
1184                                 endRendering(vkd, cmdBuffer);
1185                 }
1186
1187                 if (!m_params.groupParams->useDynamicRendering)
1188                         endRenderPass(vkd, cmdBuffer);
1189         }
1190
1191         // Prepare images for copying.
1192         const auto colorBufferBarrier = makeImageMemoryBarrier(
1193                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1194                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1195                 colorBuffer.get(), colorSubresourceRange);
1196         vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorBufferBarrier);
1197
1198         const auto dsBufferBarrier = makeImageMemoryBarrier(
1199                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1200                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1201                 dsBuffer.get(), dsSubresourceRange);
1202         vkd.cmdPipelineBarrier(cmdBuffer, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &dsBufferBarrier);
1203
1204         // Copy images to output buffers.
1205         for (deUint32 layerIdx = 0u; layerIdx < imageLayers; ++layerIdx)
1206         {
1207                 const auto colorSubresourceLayers       = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layerIdx, 1u);
1208                 const auto colorCopyRegion                      = makeBufferImageCopy(imageExtent, colorSubresourceLayers);
1209                 vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outputBuffers[layerIdx]->get(), 1u, &colorCopyRegion);
1210         }
1211
1212         // Note: this only copies the stencil aspect. See stencilOutBuffer creation.
1213         for (deUint32 layerIdx = 0u; layerIdx < imageLayers; ++layerIdx)
1214         {
1215                 const auto stencilSubresourceLayers     = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layerIdx, 1u);
1216                 const auto stencilCopyRegion            = makeBufferImageCopy(imageExtent, stencilSubresourceLayers);
1217                 vkd.cmdCopyImageToBuffer(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stencilOutBuffers[layerIdx]->get(), 1u, &stencilCopyRegion);
1218         }
1219
1220         // Prepare buffers for host reading.
1221         const auto outputBufferBarrier          = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1222         vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &outputBufferBarrier, 0u, nullptr, 0u, nullptr);
1223
1224         endCommandBuffer(vkd, cmdBuffer);
1225         submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1226
1227         // Read output buffers and verify their contents.
1228
1229         // With stride zero, mosaic meshes increment the stencil buffer as many times as draw operations for affected pixels and
1230         // overlapping meshes increment the stencil buffer only in the first draw operation (the rest fail the depth test) as many times
1231         // as triangles per draw.
1232         //
1233         // With nonzero stride, mosaic meshes increment the stencil buffer once per pixel. Overlapping meshes increment it once per
1234         // triangle.
1235         const auto      stencilIncrements               =       ((m_params.stride == 0u)
1236                                                                                         ? (isMosaic ? drawInfos.drawInfoCount() : trianglesPerDraw)
1237                                                                                         : (isMosaic ? 1u : triangleCount));
1238         const auto      maxInstanceIndex                = m_params.maxInstanceIndex();
1239         const auto      colorVerificationFormat = mapVkFormat(getVerificationFormat());
1240         const auto      iWidth                                  = static_cast<int>(imageExtent.width);
1241         const auto      iHeight                                 = static_cast<int>(imageExtent.height);
1242         auto&           log                                             = m_context.getTestContext().getLog();
1243         const auto      logMode                                 = tcu::CompareLogMode::COMPARE_LOG_ON_ERROR;
1244
1245         for (deUint32 layerIdx = 0u; layerIdx < imageLayers; ++layerIdx)
1246         {
1247                 auto& outputBufferAlloc = outputBuffers[layerIdx]->getAllocation();
1248                 invalidateAlloc(vkd, device, outputBufferAlloc);
1249                 const void* outputBufferData = outputBufferAlloc.getHostPtr();
1250
1251                 auto& stencilOutBufferAlloc = stencilOutBuffers[layerIdx]->getAllocation();
1252                 invalidateAlloc(vkd, device, stencilOutBufferAlloc);
1253                 const void* stencilOutBufferData = stencilOutBufferAlloc.getHostPtr();
1254
1255                 tcu::ConstPixelBufferAccess     colorAccess                             (colorVerificationFormat, iWidth, iHeight, 1, outputBufferData);
1256                 tcu::ConstPixelBufferAccess     stencilAccess                   (tcuStencilFmt, iWidth, iHeight, 1, stencilOutBufferData);
1257
1258                 // Generate reference images.
1259                 tcu::TextureLevel                       refColorLevel           (colorVerificationFormat, iWidth, iHeight);
1260                 tcu::PixelBufferAccess          refColorAccess          = refColorLevel.getAccess();
1261                 tcu::TextureLevel                       refStencilLevel         (tcuStencilFmt, iWidth, iHeight);
1262                 tcu::PixelBufferAccess          refStencilAccess        = refStencilLevel.getAccess();
1263                 tcu::IVec4                                      referenceColor;
1264                 int                                                     referenceStencil;
1265
1266                 for (int y = 0; y < iHeight; ++y)
1267                 for (int x = 0; x < iWidth; ++x)
1268                 {
1269                         const auto pixelNumber          = static_cast<deUint32>(y * iWidth + x);
1270                         const auto triangleIndex        = (isIndexed ? (pixelCount - 1u - pixelNumber) : pixelNumber); // Reverse order for indexed draws.
1271
1272                         if (m_params.instanceCount == 0u || drawInfos.drawInfoCount() == 0u ||
1273                                 (m_params.stride == 0u && triangleIndex >= trianglesPerDraw && isMosaic))
1274                         {
1275                                 // Some pixels may not be drawn into when there are no instances or draws, or when the stride is zero in mosaic mode.
1276                                 referenceColor          = tcu::IVec4(0, 0, 0, 0);
1277                                 referenceStencil        = 0;
1278                         }
1279                         else
1280                         {
1281                                 // This must match the vertex shader.
1282                                 //
1283                                 // With stride zero, the same block is drawn over and over again in each draw call. This affects both the draw index and
1284                                 // the values in the depth/stencil buffer and, with overlapping meshes, only the first draw passes the depth test.
1285                                 //
1286                                 // With nonzero stride, the draw index depends on the triangle index and the number of triangles per draw and, for
1287                                 // overlapping meshes, the draw index is always the last one.
1288                                 const auto drawIndex =  (m_params.stride == 0u
1289                                                                                 ? (isMosaic ? (drawInfos.drawInfoCount() - 1u) : 0u)
1290                                                                                 : (isMosaic ? (triangleIndex / trianglesPerDraw) : (drawInfos.drawInfoCount() - 1u)));
1291                                 referenceColor = tcu::IVec4(
1292                                         static_cast<int>((drawIndex >> 8) & 0xFFu),
1293                                         static_cast<int>((drawIndex     ) & 0xFFu),
1294                                         static_cast<int>(255u - maxInstanceIndex),
1295                                         static_cast<int>(255u - layerIdx));
1296
1297                                 referenceStencil = static_cast<int>((m_params.instanceCount * stencilIncrements) % 256u); // VK_STENCIL_OP_INCREMENT_AND_WRAP.
1298                         }
1299
1300                         refColorAccess.setPixel(referenceColor, x, y);
1301                         refStencilAccess.setPixStencil(referenceStencil, x, y);
1302                 }
1303
1304                 const auto layerIdxStr          = de::toString(layerIdx);
1305                 const auto colorSetName         = "ColorTestResultLayer" + layerIdxStr;
1306                 const auto stencilSetName       = "StencilTestResultLayer" + layerIdxStr;
1307
1308                 if (!tcu::intThresholdCompare(log, colorSetName.c_str(), "", refColorAccess, colorAccess, tcu::UVec4(0u, 0u, 0u, 0u), logMode))
1309                         return tcu::TestStatus::fail("Color image comparison failed; check log for more details");
1310
1311                 if (!tcu::dsThresholdCompare(log, stencilSetName.c_str(), "", refStencilAccess, stencilAccess, 0.0f, logMode))
1312                         return tcu::TestStatus::fail("Stencil image comparison failed; check log for more details");
1313         }
1314
1315         return tcu::TestStatus::pass("Pass");
1316 }
1317
1318 } // anonymous
1319
1320 tcu::TestCaseGroup*     createDrawMultiExtTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1321 {
1322         using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
1323
1324         GroupPtr drawMultiGroup (new tcu::TestCaseGroup(testCtx, "multi_draw", "VK_EXT_multi_draw tests"));
1325
1326         const struct
1327         {
1328                 MeshType        meshType;
1329                 const char*     name;
1330         } meshTypeCases[] =
1331         {
1332                 { MeshType::MOSAIC,                     "mosaic"                },
1333                 { MeshType::OVERLAPPING,        "overlapping"   },
1334         };
1335
1336         const struct
1337         {
1338                 DrawType        drawType;
1339                 const char*     name;
1340         } drawTypeCases[] =
1341         {
1342                 { DrawType::NORMAL,             "normal"        },
1343                 { DrawType::INDEXED,    "indexed"       },
1344         };
1345
1346         const struct
1347         {
1348                 tcu::Maybe<VertexOffsetType>    vertexOffsetType;
1349                 const char*                                             name;
1350         } offsetTypeCases[] =
1351         {
1352                 { tcu::Nothing,                                                 ""                      },
1353                 { VertexOffsetType::MIXED,                              "mixed"         },
1354                 { VertexOffsetType::CONSTANT_RANDOM,    "random"        },
1355                 { VertexOffsetType::CONSTANT_PACK,              "packed"        },
1356         };
1357
1358         const struct
1359         {
1360                 deUint32        drawCount;
1361                 const char*     name;
1362         } drawCountCases[] =
1363         {
1364                 { 0u,                                   "no_draws"      },
1365                 { 1u,                                   "one_draw"      },
1366                 { 16u,                                  "16_draws"      },
1367                 { getTriangleCount(),   "max_draws"     },
1368         };
1369
1370         const struct
1371         {
1372                 int                     extraBytes;
1373                 const char*     name;
1374         } strideCases[] =
1375         {
1376                 { -1,           "stride_zero"           },
1377                 {  0,           "standard_stride"       },
1378                 {  4,           "stride_extra_4"        },
1379                 { 12,           "stride_extra_12"       },
1380         };
1381
1382         const struct
1383         {
1384                 deUint32        firstInstance;
1385                 deUint32        instanceCount;
1386                 const char*     name;
1387         } instanceCases[] =
1388         {
1389                 {       0u,             0u,             "no_instances"                  },
1390                 {       0u,             1u,             "1_instance"                    },
1391                 {       0u,             10u,    "10_instances"                  },
1392                 {       3u,             2u,             "2_instances_base_3"    },
1393         };
1394
1395         const struct
1396         {
1397                 bool            useTessellation;
1398                 bool            useGeometry;
1399                 const char*     name;
1400         } shaderCases[] =
1401         {
1402                 { false,        false,          "vert_only"     },
1403                 { false,        true,           "with_geom"     },
1404                 { true,         false,          "with_tess"     },
1405                 { true,         true,           "tess_geom"     },
1406         };
1407
1408         const struct
1409         {
1410                 bool            multiview;
1411                 const char*     name;
1412         } multiviewCases[] =
1413         {
1414                 { false,        "single_view"   },
1415                 { true,         "multiview"             },
1416         };
1417
1418         constexpr deUint32 kSeed = 1621260419u;
1419
1420         for (const auto& meshTypeCase : meshTypeCases)
1421         {
1422                 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1423                 if (groupParams->useSecondaryCmdBuffer && (meshTypeCase.meshType != MeshType::MOSAIC))
1424                         continue;
1425
1426                 GroupPtr meshTypeGroup(new tcu::TestCaseGroup(testCtx, meshTypeCase.name, ""));
1427
1428                 for (const auto& drawTypeCase : drawTypeCases)
1429                 {
1430                         for (const auto& offsetTypeCase : offsetTypeCases)
1431                         {
1432                                 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1433                                 if (groupParams->useSecondaryCmdBuffer && offsetTypeCase.vertexOffsetType && (*offsetTypeCase.vertexOffsetType != VertexOffsetType::CONSTANT_RANDOM))
1434                                         continue;
1435
1436                                 const auto hasOffsetType = static_cast<bool>(offsetTypeCase.vertexOffsetType);
1437                                 if ((drawTypeCase.drawType == DrawType::NORMAL && hasOffsetType) ||
1438                                         (drawTypeCase.drawType == DrawType::INDEXED && !hasOffsetType))
1439                                 {
1440                                         continue;
1441                                 }
1442
1443                                 std::string drawGroupName = drawTypeCase.name;
1444                                 if (hasOffsetType)
1445                                         drawGroupName += std::string("_") + offsetTypeCase.name;
1446
1447                                 GroupPtr drawTypeGroup(new tcu::TestCaseGroup(testCtx, drawGroupName.c_str(), ""));
1448
1449                                 for (const auto& drawCountCase : drawCountCases)
1450                                 {
1451                                         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1452                                         if (groupParams->useSecondaryCmdBuffer && (drawCountCase.drawCount != 1u))
1453                                                 continue;
1454
1455                                         GroupPtr drawCountGroup(new tcu::TestCaseGroup(testCtx, drawCountCase.name, ""));
1456
1457                                         for (const auto& strideCase : strideCases)
1458                                         {
1459                                                 GroupPtr strideGroup(new tcu::TestCaseGroup(testCtx, strideCase.name, ""));
1460
1461                                                 for (const auto& instanceCase : instanceCases)
1462                                                 {
1463                                                         GroupPtr instanceGroup(new tcu::TestCaseGroup(testCtx, instanceCase.name, ""));
1464
1465                                                         for (const auto& shaderCase : shaderCases)
1466                                                         {
1467                                                                 GroupPtr shaderGroup(new tcu::TestCaseGroup(testCtx, shaderCase.name, ""));
1468
1469                                                                 for (const auto& multiviewCase : multiviewCases)
1470                                                                 {
1471                                                                         GroupPtr multiviewGroup(new tcu::TestCaseGroup(testCtx, multiviewCase.name, ""));
1472
1473                                                                         const auto      isIndexed       = (drawTypeCase.drawType == DrawType::INDEXED);
1474                                                                         const auto      isPacked        = (offsetTypeCase.vertexOffsetType && *offsetTypeCase.vertexOffsetType == VertexOffsetType::CONSTANT_PACK);
1475                                                                         const auto      baseStride      = ((isIndexed && !isPacked) ? sizeof(VkMultiDrawIndexedInfoEXT) : sizeof(VkMultiDrawInfoEXT));
1476                                                                         const auto&     extraBytes      = strideCase.extraBytes;
1477                                                                         const auto      testOffset      = (isIndexed ? tcu::just(VertexOffsetParams{*offsetTypeCase.vertexOffsetType, 0u }) : tcu::Nothing);
1478                                                                         deUint32        testStride      = 0u;
1479
1480                                                                         if (extraBytes >= 0)
1481                                                                                 testStride = static_cast<deUint32>(baseStride) + static_cast<deUint32>(extraBytes);
1482
1483                                                                         // For overlapping triangles we will skip instanced drawing.
1484                                                                         if (instanceCase.instanceCount > 1u && meshTypeCase.meshType == MeshType::OVERLAPPING)
1485                                                                                 continue;
1486
1487                                                                         TestParams params
1488                                                                         {
1489                                                                                 meshTypeCase.meshType,                  //      MeshType                                                meshType;
1490                                                                                 drawTypeCase.drawType,                  //      DrawType                                                drawType;
1491                                                                                 drawCountCase.drawCount,                //      deUint32                                                drawCount;
1492                                                                                 instanceCase.instanceCount,             //      deUint32                                                instanceCount;
1493                                                                                 instanceCase.firstInstance,             //      deUint32                                                firstInstance;
1494                                                                                 testStride,                                             //      deUint32                                                stride;
1495                                                                                 testOffset,                                             //      tcu::Maybe<VertexOffsetParams>> vertexOffset;   // Only used for indexed draws.
1496                                                                                 kSeed,                                                  //      deUint32                                                seed;
1497                                                                                 shaderCase.useTessellation,             //      bool                                                    useTessellation;
1498                                                                                 shaderCase.useGeometry,                 //      bool                                                    useGeometry;
1499                                                                                 multiviewCase.multiview,                //      bool                                                    multiview;
1500                                                                                 groupParams,                                    //      SharedGroupParams                               groupParams;
1501                                                                         };
1502
1503                                                                         multiviewGroup->addChild(new MultiDrawTest(testCtx, "no_offset", "", params));
1504
1505                                                                         if (isIndexed)
1506                                                                         {
1507                                                                                 params.vertexOffset->offset = 6u;
1508                                                                                 multiviewGroup->addChild(new MultiDrawTest(testCtx, "offset_6", "", params));
1509                                                                         }
1510
1511                                                                         shaderGroup->addChild(multiviewGroup.release());
1512                                                                 }
1513
1514                                                                 instanceGroup->addChild(shaderGroup.release());
1515                                                         }
1516
1517                                                         strideGroup->addChild(instanceGroup.release());
1518                                                 }
1519
1520                                                 drawCountGroup->addChild(strideGroup.release());
1521                                         }
1522
1523                                         drawTypeGroup->addChild(drawCountGroup.release());
1524                                 }
1525
1526                                 meshTypeGroup->addChild(drawTypeGroup.release());
1527                         }
1528                 }
1529
1530                 drawMultiGroup->addChild(meshTypeGroup.release());
1531         }
1532
1533         return drawMultiGroup.release();
1534 }
1535
1536 } // Draw
1537 } // vkt