Merge vk-gl-cts/vulkan-cts-1.1.6 into vk-gl-cts/vulkan-cts-1.2.1
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawIndirectTest.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel 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 Draw Indirect Test
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawIndirectTest.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktDrawTestCaseUtil.hpp"
29
30 #include "vktDrawBaseClass.hpp"
31
32 #include "tcuTestLog.hpp"
33 #include "tcuResource.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuRGBA.hpp"
37 #include "vkQueryUtil.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkCmdUtil.hpp"
41
42 namespace vkt
43 {
44 namespace Draw
45 {
46 namespace
47 {
48
49 enum
50 {
51         VERTEX_OFFSET = 13
52 };
53
54 struct JunkData
55 {
56         JunkData()
57                 : varA  (0xcd)
58                 , varB  (0xcd)
59         {
60         }
61         const deUint16  varA;
62         const deUint32  varB;
63 };
64
65 enum DrawType
66 {
67         DRAW_TYPE_SEQUENTIAL,
68         DRAW_TYPE_INDEXED,
69
70         DRAWTYPE_LAST
71 };
72
73 struct DrawTypedTestSpec : public TestSpecBase
74 {
75         DrawTypedTestSpec()
76                 : testFirstInstanceNdx(false)
77                 , testIndirectCountExt(false)
78         {};
79
80         DrawType        drawType;
81         bool            testFirstInstanceNdx;
82         bool            testIndirectCountExt;
83 };
84
85 class IndirectDraw : public DrawTestsBaseClass
86 {
87 public:
88         typedef DrawTypedTestSpec       TestSpec;
89
90                                                                 IndirectDraw    (Context &context, TestSpec testSpec);
91         virtual tcu::TestStatus         iterate                 (void);
92
93         template<typename T> void       addCommand              (const T&);
94
95 protected:
96         void                                            setVertexBuffer                                         (void);
97         void                                            setFirstInstanceVertexBuffer            (void);
98
99         std::vector<char>                       m_indirectBufferContents;
100         de::SharedPtr<Buffer>           m_indirectBuffer;
101         vk::VkDeviceSize                        m_offsetInBuffer;
102         deUint32                                        m_strideInBuffer;
103
104         const bool                                      m_testIndirectCountExt;
105         de::SharedPtr<Buffer>           m_indirectCountBuffer;
106         vk::VkDeviceSize                        m_offsetInCountBuffer;
107         const deUint32                          m_indirectCountExtDrawPadding;
108
109         deUint32                                        m_drawCount;
110         JunkData                                        m_junkData;
111
112         const DrawType                          m_drawType;
113         const bool                                      m_testFirstInstanceNdx;
114         deBool                                          m_isMultiDrawEnabled;
115         deUint32                                        m_drawIndirectMaxCount;
116
117         de::SharedPtr<Buffer>           m_indexBuffer;
118 };
119
120 struct FirstInstanceSupported
121 {
122         static deUint32 getFirstInstance        (void)                                                                                  { return 2; }
123         static bool             isTestSupported         (const vk::VkPhysicalDeviceFeatures& features)  { return features.drawIndirectFirstInstance == VK_TRUE; }
124 };
125
126 struct FirstInstanceNotSupported
127 {
128         static deUint32 getFirstInstance        (void)                                                                                  { return 0; }
129         static bool             isTestSupported         (const vk::VkPhysicalDeviceFeatures&)                   { return true; }
130 };
131
132 template<class FirstInstanceSupport>
133 class IndirectDrawInstanced : public IndirectDraw
134 {
135 public:
136                                                                 IndirectDrawInstanced   (Context &context, TestSpec testSpec);
137         virtual tcu::TestStatus         iterate                                 (void);
138 };
139
140 void IndirectDraw::setVertexBuffer (void)
141 {
142         int refVertexIndex = 2;
143
144         if (m_drawType == DRAW_TYPE_INDEXED)
145         {
146                 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
147                 {
148                         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
149                 }
150                 refVertexIndex += VERTEX_OFFSET;
151         }
152
153         m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
154         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
155
156         switch (m_topology)
157         {
158                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
159                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
160                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
161                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
162                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
163                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
164                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
165                         break;
166                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
167                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
168                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
169                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,     -0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
170                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
171                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
172                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
173                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
174                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refVertexIndex++));
175                         break;
176                 default:
177                         DE_FATAL("Unknown topology");
178                         break;
179         }
180
181         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
182 }
183
184 void IndirectDraw::setFirstInstanceVertexBuffer (void)
185 {
186         if (m_context.getDeviceFeatures().drawIndirectFirstInstance != VK_TRUE)
187         {
188                 TCU_THROW(NotSupportedError, "Required 'drawIndirectFirstInstance' feature is not supported");
189         }
190
191         if (m_drawType == DRAW_TYPE_INDEXED)
192         {
193                 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
194                 {
195                         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
196                 }
197         }
198
199         m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
200         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
201
202         switch (m_topology)
203         {
204                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
205                 {
206                         int refInstanceIndex = 1;
207                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
208                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
209                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
210
211                         refInstanceIndex = 0;
212                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
213                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
214                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
215                         break;
216                 }
217                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
218                 {
219                         int refInstanceIndex = 1;
220                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
221                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
222                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,     -0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
223                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
224
225                         refInstanceIndex = 0;
226                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
227                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
228                         m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
229                         m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
230                         break;
231                 }
232                 default:
233                         DE_FATAL("Unknown topology");
234                         break;
235         }
236
237         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
238 }
239
240 IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
241         : DrawTestsBaseClass                            (context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
242         , m_testIndirectCountExt                        (testSpec.testIndirectCountExt)
243         , m_indirectCountExtDrawPadding         (1u)
244         , m_drawType                                            (testSpec.drawType)
245         , m_testFirstInstanceNdx                        (testSpec.testFirstInstanceNdx)
246 {
247         if (m_testFirstInstanceNdx)
248                 setFirstInstanceVertexBuffer();
249         else
250                 setVertexBuffer();
251
252         initialize();
253
254         if (testSpec.drawType == DRAW_TYPE_INDEXED)
255         {
256                 const size_t indexBufferLength = m_data.size() - VERTEX_OFFSET;
257
258                 m_indexBuffer = Buffer::createAndAlloc(m_vk, m_context.getDevice(), BufferCreateInfo(sizeof(deUint32) * indexBufferLength, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
259                 deUint32* indices = reinterpret_cast<deUint32*>(m_indexBuffer->getBoundMemory().getHostPtr());
260                 for (size_t i = 0; i < indexBufferLength; i++)
261                 {
262                         indices[i] = static_cast<deUint32>(i);
263                 }
264                 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
265         }
266
267         // Check device for multidraw support:
268         if (!m_context.getDeviceFeatures().multiDrawIndirect || m_testFirstInstanceNdx)
269                 m_isMultiDrawEnabled = false;
270         else
271                 m_isMultiDrawEnabled = true;
272
273         m_drawIndirectMaxCount = m_context.getDeviceProperties().limits.maxDrawIndirectCount;
274 }
275
276 template<>
277 void IndirectDraw::addCommand<vk::VkDrawIndirectCommand> (const vk::VkDrawIndirectCommand& command)
278 {
279         DE_ASSERT(m_drawType == DRAW_TYPE_SEQUENTIAL);
280
281         const size_t currentSize = m_indirectBufferContents.size();
282
283         m_indirectBufferContents.resize(currentSize + sizeof(command));
284
285         deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
286 }
287
288 template<>
289 void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand> (const vk::VkDrawIndexedIndirectCommand& command)
290 {
291         DE_ASSERT(m_drawType == DRAW_TYPE_INDEXED);
292
293         const size_t currentSize = m_indirectBufferContents.size();
294
295         m_indirectBufferContents.resize(currentSize + sizeof(command));
296
297         deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
298 }
299
300 tcu::TestStatus IndirectDraw::iterate (void)
301 {
302         tcu::TestLog&           log             = m_context.getTestContext().getLog();
303         const vk::VkQueue       queue   = m_context.getUniversalQueue();
304         const vk::VkDevice      device  = m_context.getDevice();
305
306         if (m_drawType == DRAW_TYPE_SEQUENTIAL)
307         {
308                 switch (m_topology)
309                 {
310                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
311                 {
312                         vk::VkDrawIndirectCommand drawCommands[] =
313                         {
314                                 {
315                                         3u,                                                                     //vertexCount
316                                         1u,                                                                     //instanceCount
317                                         2u,                                                                     //firstVertex
318                                         (m_testFirstInstanceNdx ? 1u : 0u)      //firstInstance
319                                 },
320                                 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
321                                 {
322                                         3u,                                                                     //vertexCount
323                                         1u,                                                                     //instanceCount
324                                         5u,                                                                     //firstVertex
325                                         0u                                                                      //firstInstance
326                                 }
327                         };
328                         addCommand(drawCommands[0]);
329                         addCommand(drawCommands[1]);
330                         addCommand(drawCommands[2]);
331                         if (m_testIndirectCountExt)
332                         {
333                                 addCommand(drawCommands[1]);
334                                 addCommand(drawCommands[1]);
335                         }
336                         break;
337                 }
338                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
339                 {
340                         vk::VkDrawIndirectCommand drawCommands[] =
341                         {
342                                 {
343                                         4u,                                                                     //vertexCount
344                                         1u,                                                                     //instanceCount
345                                         2u,                                                                     //firstVertex
346                                         (m_testFirstInstanceNdx ? 1u : 0u)      //firstInstance
347                                 },
348                                 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
349                                 {
350                                         4u,                                                                     //vertexCount
351                                         1u,                                                                     //instanceCount
352                                         6u,                                                                     //firstVertex
353                                         0u                                                                      //firstInstance
354                                 }
355                         };
356                         addCommand(drawCommands[0]);
357                         addCommand(drawCommands[1]);
358                         addCommand(drawCommands[2]);
359                         if (m_testIndirectCountExt)
360                         {
361                                 addCommand(drawCommands[1]);
362                                 addCommand(drawCommands[1]);
363                         }
364                         break;
365                 }
366                 default:
367                         TCU_FAIL("impossible");
368                 }
369
370                 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
371         }
372         else if (m_drawType == DRAW_TYPE_INDEXED)
373         {
374                 switch (m_topology)
375                 {
376                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
377                 {
378                         vk::VkDrawIndexedIndirectCommand drawCommands[] =
379                         {
380                                 {
381                                         3u,                                                                     // indexCount
382                                         1u,                                                                     // instanceCount
383                                         2u,                                                                     // firstIndex
384                                         VERTEX_OFFSET,                                          // vertexOffset
385                                         (m_testFirstInstanceNdx ? 1u : 0u),     // firstInstance
386                                 },
387                                 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
388                                 {
389                                         3u,                                                                     // indexCount
390                                         1u,                                                                     // instanceCount
391                                         5u,                                                                     // firstIndex
392                                         VERTEX_OFFSET,                                          // vertexOffset
393                                         0u                                                                      // firstInstance
394                                 }
395                         };
396                         addCommand(drawCommands[0]);
397                         addCommand(drawCommands[1]);
398                         addCommand(drawCommands[2]);
399                         if (m_testIndirectCountExt)
400                         {
401                                 addCommand(drawCommands[1]);
402                                 addCommand(drawCommands[1]);
403                         }
404                         break;
405                 }
406                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
407                 {
408                         vk::VkDrawIndexedIndirectCommand drawCommands[] =
409                         {
410                                 {
411                                         4u,                                                                     // indexCount
412                                         1u,                                                                     // instanceCount
413                                         2u,                                                                     // firstIndex
414                                         VERTEX_OFFSET,                                          // vertexOffset
415                                         (m_testFirstInstanceNdx ? 1u : 0u),     // firstInstance
416                                 },
417                                 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
418                                 {
419                                         4u,                                                                     // indexCount
420                                         1u,                                                                     // instanceCount
421                                         6u,                                                                     // firstIndex
422                                         VERTEX_OFFSET,                                          // vertexOffset
423                                         0u                                                                      // firstInstance
424                                 }
425                         };
426                         addCommand(drawCommands[0]);
427                         addCommand(drawCommands[1]);
428                         addCommand(drawCommands[2]);
429                         if (m_testIndirectCountExt)
430                         {
431                                 addCommand(drawCommands[1]);
432                                 addCommand(drawCommands[1]);
433                         }
434                         break;
435                 }
436                 default:
437                         TCU_FAIL("impossible");
438                 }
439
440                 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
441         }
442
443         m_drawCount                     = 2;
444         m_offsetInBuffer        = sizeof(m_junkData);
445
446         beginRenderPass();
447
448         const vk::VkDeviceSize vertexBufferOffset       = 0;
449         const vk::VkBuffer vertexBuffer                         = m_vertexBuffer->object();
450
451         m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
452
453         const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
454
455         m_indirectBuffer = Buffer::createAndAlloc(      m_vk,
456                                                                                                 m_context.getDevice(),
457                                                                                                 BufferCreateInfo(dataSize + m_offsetInBuffer,
458                                                                                                                                  vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
459                                                                                                 m_context.getDefaultAllocator(),
460                                                                                                 vk::MemoryRequirement::HostVisible);
461
462         deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
463
464         deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
465         deMemcpy(ptr + m_offsetInBuffer, &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
466
467         vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
468
469         if (m_testIndirectCountExt)
470         {
471                 m_offsetInCountBuffer = sizeof(tcu::Vec3);
472                 m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
473                                                                                                            m_context.getDevice(),
474                                                                                                            BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
475                                                                                                                                                 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
476                                                                                                            m_context.getDefaultAllocator(),
477                                                                                                            vk::MemoryRequirement::HostVisible);
478
479                 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
480
481                 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
482                         *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount;
483                 else
484                         *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
485
486                 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
487         }
488
489         m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
490
491         if (m_drawType == DRAW_TYPE_INDEXED)
492         {
493                 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
494         }
495
496         if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
497         {
498                 switch (m_drawType)
499                 {
500                         case DRAW_TYPE_SEQUENTIAL:
501                         {
502                                 if (m_testIndirectCountExt)
503                                         m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
504                                                                                           m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
505                                                                                           m_strideInBuffer);
506                                 else
507                                         m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
508                                 break;
509                         }
510                         case DRAW_TYPE_INDEXED:
511                         {
512                                 if (m_testIndirectCountExt)
513                                         m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
514                                                                                                          m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
515                                                                                                          m_strideInBuffer);
516                                 else
517                                         m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
518                                 break;
519                         }
520                         default:
521                                 TCU_FAIL("impossible");
522                 }
523         }
524         else
525         {
526                 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
527                 {
528                         switch (m_drawType)
529                         {
530                                 case DRAW_TYPE_SEQUENTIAL:
531                                 {
532                                         if (m_testIndirectCountExt)
533                                                 m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
534                                                                                                   m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
535                                                                                                   m_strideInBuffer);
536                                         else
537                                                 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
538                                         break;
539                                 }
540                                 case DRAW_TYPE_INDEXED:
541                                 {
542                                         if (m_testIndirectCountExt)
543                                                 m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
544                                                                                                                  m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
545                                                                                                                  m_strideInBuffer);
546                                         else
547                                                 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
548                                         break;
549                                 }
550                                 default:
551                                         TCU_FAIL("impossible");
552                         }
553                 }
554         }
555         endRenderPass(m_vk, *m_cmdBuffer);
556         endCommandBuffer(m_vk, *m_cmdBuffer);
557
558         submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
559
560         // Validation
561         tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
562         referenceFrame.allocLevel(0);
563
564         const deInt32 frameWidth        = referenceFrame.getWidth();
565         const deInt32 frameHeight       = referenceFrame.getHeight();
566
567         tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
568
569         ReferenceImageCoordinates refCoords;
570
571         for (int y = 0; y < frameHeight; y++)
572         {
573                 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
574
575                 for (int x = 0; x < frameWidth; x++)
576                 {
577                         const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
578
579                         if ((yCoord >= refCoords.bottom &&
580                                  yCoord <= refCoords.top        &&
581                                  xCoord >= refCoords.left       &&
582                                  xCoord <= refCoords.right))
583                                 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
584                 }
585         }
586
587         const vk::VkOffset3D zeroOffset                                 = { 0, 0, 0 };
588         const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
589                 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
590
591         qpTestResult res = QP_TEST_RESULT_PASS;
592
593         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
594                 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
595         {
596                 res = QP_TEST_RESULT_FAIL;
597         }
598
599         return tcu::TestStatus(res, qpGetTestResultName(res));
600 }
601
602 template<class FirstInstanceSupport>
603 IndirectDrawInstanced<FirstInstanceSupport>::IndirectDrawInstanced (Context &context, TestSpec testSpec)
604         : IndirectDraw(context, testSpec)
605 {
606         if (!FirstInstanceSupport::isTestSupported(m_context.getDeviceFeatures()))
607         {
608                 throw tcu::NotSupportedError("Required 'drawIndirectFirstInstance' feature is not supported");
609         }
610 }
611
612 template<class FirstInstanceSupport>
613 tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
614 {
615         tcu::TestLog&           log             = m_context.getTestContext().getLog();
616         const vk::VkQueue       queue   = m_context.getUniversalQueue();
617         const vk::VkDevice      device  = m_context.getDevice();
618
619         if (m_drawType == DRAW_TYPE_SEQUENTIAL)
620         {
621                 switch (m_topology)
622                 {
623                         case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
624                         {
625                                 vk::VkDrawIndirectCommand drawCmd[] =
626                                 {
627                                         {
628                                                 3,                                                                                      //vertexCount
629                                                 4,                                                                                      //instanceCount
630                                                 2,                                                                                      //firstVertex
631                                                 FirstInstanceSupport::getFirstInstance()        //firstInstance
632                                         },
633                                         { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
634                                         {
635                                                 3,                                                                                      //vertexCount
636                                                 4,                                                                                      //instanceCount
637                                                 5,                                                                                      //firstVertex
638                                                 FirstInstanceSupport::getFirstInstance()        //firstInstance
639                                         }
640                                 };
641                                 addCommand(drawCmd[0]);
642                                 addCommand(drawCmd[1]);
643                                 addCommand(drawCmd[2]);
644                                 if (m_testIndirectCountExt)
645                                 {
646                                         addCommand(drawCmd[1]);
647                                         addCommand(drawCmd[1]);
648                                 }
649                                 break;
650                         }
651                         case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
652                         {
653                                 vk::VkDrawIndirectCommand drawCmd[] =
654                                 {
655                                         {
656                                                 4,                                                                                      //vertexCount
657                                                 4,                                                                                      //instanceCount
658                                                 2,                                                                                      //firstVertex
659                                                 FirstInstanceSupport::getFirstInstance()        //firstInstance
660                                         },
661                                         { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 },
662                                         {
663                                                 4,                                                                                      //vertexCount
664                                                 4,                                                                                      //instanceCount
665                                                 6,                                                                                      //firstVertex
666                                                 FirstInstanceSupport::getFirstInstance()        //firstInstance
667                                         }
668                                 };
669                                 addCommand(drawCmd[0]);
670                                 addCommand(drawCmd[1]);
671                                 addCommand(drawCmd[2]);
672                                 if (m_testIndirectCountExt)
673                                 {
674                                         addCommand(drawCmd[1]);
675                                         addCommand(drawCmd[1]);
676                                 }
677                                 break;
678                         }
679                         default:
680                                 TCU_FAIL("impossible");
681                                 break;
682                 }
683
684                 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
685         }
686         else if (m_drawType == DRAW_TYPE_INDEXED)
687         {
688                 switch (m_topology)
689                 {
690                         case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
691                         {
692                                 vk::VkDrawIndexedIndirectCommand drawCmd[] =
693                                 {
694                                         {
695                                                 3,                                                                                      // indexCount
696                                                 4,                                                                                      // instanceCount
697                                                 2,                                                                                      // firstIndex
698                                                 VERTEX_OFFSET,                                                          // vertexOffset
699                                                 FirstInstanceSupport::getFirstInstance()        // firstInstance
700                                         },
701                                         { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 },        // junk (stride)
702                                         {
703                                                 3,                                                                                      // indexCount
704                                                 4,                                                                                      // instanceCount
705                                                 5,                                                                                      // firstIndex
706                                                 VERTEX_OFFSET,                                                          // vertexOffset
707                                                 FirstInstanceSupport::getFirstInstance()        // firstInstance
708                                         }
709                                 };
710                                 addCommand(drawCmd[0]);
711                                 addCommand(drawCmd[1]);
712                                 addCommand(drawCmd[2]);
713                                 if (m_testIndirectCountExt)
714                                 {
715                                         addCommand(drawCmd[1]);
716                                         addCommand(drawCmd[1]);
717                                 }
718                                 break;
719                         }
720                         case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
721                         {
722                                 vk::VkDrawIndexedIndirectCommand drawCmd[] =
723                                 {
724                                         {
725                                                 4,                                                                                      // indexCount
726                                                 4,                                                                                      // instanceCount
727                                                 2,                                                                                      // firstIndex
728                                                 VERTEX_OFFSET,                                                          // vertexOffset
729                                                 FirstInstanceSupport::getFirstInstance()        // firstInstance
730                                         },
731                                         { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 },        // junk (stride)
732                                         {
733                                                 4,                                                                                      // indexCount
734                                                 4,                                                                                      // instanceCount
735                                                 6,                                                                                      // firstIndex
736                                                 VERTEX_OFFSET,                                                          // vertexOffset
737                                                 FirstInstanceSupport::getFirstInstance()        // firstInstance
738                                         }
739                                 };
740                                 addCommand(drawCmd[0]);
741                                 addCommand(drawCmd[1]);
742                                 addCommand(drawCmd[2]);
743                                 if (m_testIndirectCountExt)
744                                 {
745                                         addCommand(drawCmd[1]);
746                                         addCommand(drawCmd[1]);
747                                 }
748                                 break;
749                         }
750                         default:
751                                 TCU_FAIL("impossible");
752                                 break;
753                 }
754
755                 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
756         }
757
758         m_drawCount                     = 2;
759         m_offsetInBuffer        = sizeof(m_junkData);
760
761         beginRenderPass();
762
763         const vk::VkDeviceSize vertexBufferOffset = 0;
764         const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
765
766         m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
767
768         const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
769
770         m_indirectBuffer = Buffer::createAndAlloc(      m_vk,
771                                                                                                 m_context.getDevice(),
772                                                                                                 BufferCreateInfo(dataSize + m_offsetInBuffer,
773                                                                                                                                  vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
774                                                                                                 m_context.getDefaultAllocator(),
775                                                                                                 vk::MemoryRequirement::HostVisible);
776
777         deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
778
779         deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
780         deMemcpy((ptr + m_offsetInBuffer), &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
781
782         vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
783
784         if (m_testIndirectCountExt)
785         {
786                 m_offsetInCountBuffer = sizeof(tcu::Vec3);
787                 m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
788                                                                                                            m_context.getDevice(),
789                                                                                                            BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
790                                                                                                                                                 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
791                                                                                                            m_context.getDefaultAllocator(),
792                                                                                                            vk::MemoryRequirement::HostVisible);
793
794                 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
795
796                 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
797                         *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount;
798                 else
799                         *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
800
801                 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
802         }
803
804         m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
805
806         if (m_drawType == DRAW_TYPE_INDEXED)
807         {
808                 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
809         }
810
811         if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
812         {
813                 switch (m_drawType)
814                 {
815                         case DRAW_TYPE_SEQUENTIAL:
816                         {
817                                 if (m_testIndirectCountExt)
818                                         m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
819                                                                                           m_indirectCountBuffer->object(), m_offsetInCountBuffer,
820                                                                                           m_drawCount + m_indirectCountExtDrawPadding, m_strideInBuffer);
821                                 else
822                                         m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
823                                 break;
824                         }
825                         case DRAW_TYPE_INDEXED:
826                         {
827                                 if (m_testIndirectCountExt)
828                                         m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
829                                                                                                          m_indirectCountBuffer->object(), m_offsetInCountBuffer,
830                                                                                                          m_drawCount + m_indirectCountExtDrawPadding, m_strideInBuffer);
831                                 else
832                                         m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
833                                 break;
834                         }
835                         default:
836                                 TCU_FAIL("impossible");
837                 }
838         }
839         else
840         {
841                 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
842                 {
843                         switch (m_drawType)
844                         {
845                                 case DRAW_TYPE_SEQUENTIAL:
846                                 {
847                                         if (m_testIndirectCountExt)
848                                                 m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
849                                                                                                   m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
850                                                                                                   m_strideInBuffer);
851                                         else
852                                                 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
853                                         break;
854                                 }
855                                 case DRAW_TYPE_INDEXED:
856                                 {
857                                         if (m_testIndirectCountExt)
858                                                 m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
859                                                                                                                  m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
860                                                                                                                  m_strideInBuffer);
861                                         else
862                                                 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
863                                         break;
864                                 }
865                                 default:
866                                         TCU_FAIL("impossible");
867                         }
868                 }
869         }
870         endRenderPass(m_vk, *m_cmdBuffer);
871         endCommandBuffer(m_vk, *m_cmdBuffer);
872
873         submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
874
875         // Validation
876         VK_CHECK(m_vk.queueWaitIdle(queue));
877
878         tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5 + static_cast<float>(HEIGHT)));
879
880         referenceFrame.allocLevel(0);
881
882         const deInt32 frameWidth        = referenceFrame.getWidth();
883         const deInt32 frameHeight       = referenceFrame.getHeight();
884
885         tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
886
887         ReferenceImageInstancedCoordinates refInstancedCoords;
888
889         for (int y = 0; y < frameHeight; y++)
890         {
891                 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
892
893                 for (int x = 0; x < frameWidth; x++)
894                 {
895                         const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
896
897                         if ((yCoord >= refInstancedCoords.bottom        &&
898                                  yCoord <= refInstancedCoords.top               &&
899                                  xCoord >= refInstancedCoords.left              &&
900                                  xCoord <= refInstancedCoords.right))
901                                 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
902                 }
903         }
904
905         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
906         const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
907                 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
908
909         qpTestResult res = QP_TEST_RESULT_PASS;
910
911         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
912                 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
913         {
914                 res = QP_TEST_RESULT_FAIL;
915         }
916
917         return tcu::TestStatus(res, qpGetTestResultName(res));
918 }
919
920 void checkIndirectCountExt (Context& context)
921 {
922         context.requireDeviceFunctionality("VK_KHR_draw_indirect_count");
923 }
924
925 }       // anonymous
926
927 IndirectDrawTests::IndirectDrawTests (tcu::TestContext& testCtx)
928         : TestCaseGroup(testCtx, "indirect_draw", "indirect drawing simple geometry")
929 {
930         /* Left blank on purpose */
931 }
932
933 IndirectDrawTests::~IndirectDrawTests (void) {}
934
935
936 void IndirectDrawTests::init (void)
937 {
938         for (int drawTypeIdx = 0; drawTypeIdx < DRAWTYPE_LAST; drawTypeIdx++)
939         {
940                 std::string drawTypeStr;
941                 switch (drawTypeIdx)
942                 {
943                         case DRAW_TYPE_SEQUENTIAL:
944                                 drawTypeStr = "sequential";
945                                 break;
946                         case DRAW_TYPE_INDEXED:
947                                 drawTypeStr = "indexed";
948                                 break;
949                         default:
950                                 TCU_FAIL("impossible");
951                 }
952
953                 tcu::TestCaseGroup* drawTypeGroup = new tcu::TestCaseGroup(m_testCtx, drawTypeStr.c_str(), ("Draws geometry using " + drawTypeStr + "draw call").c_str());
954                 {
955                         tcu::TestCaseGroup* indirectDrawGroup           = new tcu::TestCaseGroup(m_testCtx, "indirect_draw", "Draws geometry");
956                         tcu::TestCaseGroup* indirectDrawCountGroup      = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count", "Draws geometry with VK_KHR_draw_indirect_count extension");
957                         {
958                                 IndirectDraw::TestSpec testSpec;
959                                 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
960                                 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetch.vert";
961                                 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
962                                 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
963                                 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
964                                 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
965                                 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
966
967                                 testSpec.testIndirectCountExt = true;
968                                 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
969                                 indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_list", "Draws triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
970                                 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
971                                 indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
972                         }
973                         drawTypeGroup->addChild(indirectDrawGroup);
974                         drawTypeGroup->addChild(indirectDrawCountGroup);
975
976                         {
977                                 tcu::TestCaseGroup* indirectDrawFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_first_instance", "Draws geometry with different first instance in one commandbuffer");
978                                 tcu::TestCaseGroup* indirectDrawCountFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count_first_instance", "Draws geometry with VK_KHR_draw_indirect_count extension with different first instance in one commandbuffer using ");
979                                 {
980                                         IndirectDraw::TestSpec testSpec;
981                                         testSpec.testFirstInstanceNdx = true;
982                                         testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
983                                         testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanceIndex.vert";
984                                         testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
985                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
986                                         indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
987                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
988                                         indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
989
990                                         testSpec.testIndirectCountExt = true;
991                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
992                                         indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_list", "Draws triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
993                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
994                                         indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
995                                 }
996                                 drawTypeGroup->addChild(indirectDrawFirstInstanceGroup);
997                                 drawTypeGroup->addChild(indirectDrawCountFirstInstanceGroup);
998                         }
999
1000                         tcu::TestCaseGroup* indirectDrawInstancedGroup          = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_instanced", "Draws an instanced geometry");
1001                         tcu::TestCaseGroup* indirectDrawCountInstancedGroup     = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count_instanced", "Draws an instanced geometry with VK_KHR_draw_indirect_count extension");
1002                         {
1003                                 tcu::TestCaseGroup*     indirectDrawNoFirstInstanceGroup                = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1004                                 tcu::TestCaseGroup*     indirectDrawCountNoFirstInstanceGroup   = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1005                                 {
1006                                         IndirectDrawInstanced<FirstInstanceNotSupported>::TestSpec testSpec;
1007                                         testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1008
1009                                         testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanced.vert";
1010                                         testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1011
1012                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1013                                         indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1014                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1015                                         indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1016                                         testSpec.testIndirectCountExt = true;
1017                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1018                                         indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported>, FunctionSupport0>(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1019                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1020                                         indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported>, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1021                                 }
1022                                 indirectDrawInstancedGroup->addChild(indirectDrawNoFirstInstanceGroup);
1023                                 indirectDrawCountInstancedGroup->addChild(indirectDrawCountNoFirstInstanceGroup);
1024
1025                                 tcu::TestCaseGroup*     indirectDrawFirstInstanceGroup          = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1026                                 tcu::TestCaseGroup*     indirectDrawCountFirstInstanceGroup     = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1027                                 {
1028                                         IndirectDrawInstanced<FirstInstanceSupported>::TestSpec testSpec;
1029                                         testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1030
1031                                         testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
1032                                         testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1033
1034                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1035                                         indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1036                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1037                                         indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1038
1039                                         testSpec.testIndirectCountExt = true;
1040                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1041                                         indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported>, FunctionSupport0>(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1042                                         testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1043                                         indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported>, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1044                                 }
1045                                 indirectDrawInstancedGroup->addChild(indirectDrawFirstInstanceGroup);
1046                                 indirectDrawCountInstancedGroup->addChild(indirectDrawCountFirstInstanceGroup);
1047                         }
1048                         drawTypeGroup->addChild(indirectDrawInstancedGroup);
1049                         drawTypeGroup->addChild(indirectDrawCountInstancedGroup);
1050                 }
1051
1052                 addChild(drawTypeGroup);
1053         }
1054 }
1055
1056 }       // DrawTests
1057 }       // vkt