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 {
JunkDatavkt::Draw::__anond6a1db510111::JunkData56 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 {
DrawTypedTestSpecvkt::Draw::__anond6a1db510111::DrawTypedTestSpec75 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 {
getFirstInstancevkt::Draw::__anond6a1db510111::FirstInstanceSupported122 static deUint32 getFirstInstance (void) { return 2; }
isTestSupportedvkt::Draw::__anond6a1db510111::FirstInstanceSupported123 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures& features) { return features.drawIndirectFirstInstance == VK_TRUE; }
124 };
125
126 struct FirstInstanceNotSupported
127 {
getFirstInstancevkt::Draw::__anond6a1db510111::FirstInstanceNotSupported128 static deUint32 getFirstInstance (void) { return 0; }
isTestSupportedvkt::Draw::__anond6a1db510111::FirstInstanceNotSupported129 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
setVertexBuffer(void)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
setFirstInstanceVertexBuffer(void)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
IndirectDraw(Context & context,TestSpec testSpec)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_testIndirectCountExt && !vk::isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_KHR_draw_indirect_count"))
248 TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_draw_indirect_count");
249
250 if (m_testFirstInstanceNdx)
251 setFirstInstanceVertexBuffer();
252 else
253 setVertexBuffer();
254
255 initialize();
256
257 if (testSpec.drawType == DRAW_TYPE_INDEXED)
258 {
259 const size_t indexBufferLength = m_data.size() - VERTEX_OFFSET;
260
261 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);
262 deUint32* indices = reinterpret_cast<deUint32*>(m_indexBuffer->getBoundMemory().getHostPtr());
263 for (size_t i = 0; i < indexBufferLength; i++)
264 {
265 indices[i] = static_cast<deUint32>(i);
266 }
267 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
268 }
269
270 // Check device for multidraw support:
271 if (!m_context.getDeviceFeatures().multiDrawIndirect || m_testFirstInstanceNdx)
272 m_isMultiDrawEnabled = false;
273 else
274 m_isMultiDrawEnabled = true;
275
276 m_drawIndirectMaxCount = m_context.getDeviceProperties().limits.maxDrawIndirectCount;
277 }
278
279 template<>
addCommand(const vk::VkDrawIndirectCommand & command)280 void IndirectDraw::addCommand<vk::VkDrawIndirectCommand> (const vk::VkDrawIndirectCommand& command)
281 {
282 DE_ASSERT(m_drawType == DRAW_TYPE_SEQUENTIAL);
283
284 const size_t currentSize = m_indirectBufferContents.size();
285
286 m_indirectBufferContents.resize(currentSize + sizeof(command));
287
288 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
289 }
290
291 template<>
addCommand(const vk::VkDrawIndexedIndirectCommand & command)292 void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand> (const vk::VkDrawIndexedIndirectCommand& command)
293 {
294 DE_ASSERT(m_drawType == DRAW_TYPE_INDEXED);
295
296 const size_t currentSize = m_indirectBufferContents.size();
297
298 m_indirectBufferContents.resize(currentSize + sizeof(command));
299
300 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
301 }
302
iterate(void)303 tcu::TestStatus IndirectDraw::iterate (void)
304 {
305 tcu::TestLog& log = m_context.getTestContext().getLog();
306 const vk::VkQueue queue = m_context.getUniversalQueue();
307 const vk::VkDevice device = m_context.getDevice();
308
309 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
310 {
311 switch (m_topology)
312 {
313 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
314 {
315 vk::VkDrawIndirectCommand drawCommands[] =
316 {
317 {
318 3u, //vertexCount
319 1u, //instanceCount
320 2u, //firstVertex
321 (m_testFirstInstanceNdx ? 1u : 0u) //firstInstance
322 },
323 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
324 {
325 3u, //vertexCount
326 1u, //instanceCount
327 5u, //firstVertex
328 0u //firstInstance
329 }
330 };
331 addCommand(drawCommands[0]);
332 addCommand(drawCommands[1]);
333 addCommand(drawCommands[2]);
334 if (m_testIndirectCountExt)
335 {
336 addCommand(drawCommands[1]);
337 addCommand(drawCommands[1]);
338 }
339 break;
340 }
341 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
342 {
343 vk::VkDrawIndirectCommand drawCommands[] =
344 {
345 {
346 4u, //vertexCount
347 1u, //instanceCount
348 2u, //firstVertex
349 (m_testFirstInstanceNdx ? 1u : 0u) //firstInstance
350 },
351 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
352 {
353 4u, //vertexCount
354 1u, //instanceCount
355 6u, //firstVertex
356 0u //firstInstance
357 }
358 };
359 addCommand(drawCommands[0]);
360 addCommand(drawCommands[1]);
361 addCommand(drawCommands[2]);
362 if (m_testIndirectCountExt)
363 {
364 addCommand(drawCommands[1]);
365 addCommand(drawCommands[1]);
366 }
367 break;
368 }
369 default:
370 TCU_FAIL("impossible");
371 }
372
373 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
374 }
375 else if (m_drawType == DRAW_TYPE_INDEXED)
376 {
377 switch (m_topology)
378 {
379 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
380 {
381 vk::VkDrawIndexedIndirectCommand drawCommands[] =
382 {
383 {
384 3u, // indexCount
385 1u, // instanceCount
386 2u, // firstIndex
387 VERTEX_OFFSET, // vertexOffset
388 (m_testFirstInstanceNdx ? 1u : 0u), // firstInstance
389 },
390 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
391 {
392 3u, // indexCount
393 1u, // instanceCount
394 5u, // firstIndex
395 VERTEX_OFFSET, // vertexOffset
396 0u // firstInstance
397 }
398 };
399 addCommand(drawCommands[0]);
400 addCommand(drawCommands[1]);
401 addCommand(drawCommands[2]);
402 if (m_testIndirectCountExt)
403 {
404 addCommand(drawCommands[1]);
405 addCommand(drawCommands[1]);
406 }
407 break;
408 }
409 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
410 {
411 vk::VkDrawIndexedIndirectCommand drawCommands[] =
412 {
413 {
414 4u, // indexCount
415 1u, // instanceCount
416 2u, // firstIndex
417 VERTEX_OFFSET, // vertexOffset
418 (m_testFirstInstanceNdx ? 1u : 0u), // firstInstance
419 },
420 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
421 {
422 4u, // indexCount
423 1u, // instanceCount
424 6u, // firstIndex
425 VERTEX_OFFSET, // vertexOffset
426 0u // firstInstance
427 }
428 };
429 addCommand(drawCommands[0]);
430 addCommand(drawCommands[1]);
431 addCommand(drawCommands[2]);
432 if (m_testIndirectCountExt)
433 {
434 addCommand(drawCommands[1]);
435 addCommand(drawCommands[1]);
436 }
437 break;
438 }
439 default:
440 TCU_FAIL("impossible");
441 }
442
443 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
444 }
445
446 m_drawCount = 2;
447 m_offsetInBuffer = sizeof(m_junkData);
448
449 beginRenderPass();
450
451 const vk::VkDeviceSize vertexBufferOffset = 0;
452 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
453
454 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
455
456 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
457
458 m_indirectBuffer = Buffer::createAndAlloc( m_vk,
459 m_context.getDevice(),
460 BufferCreateInfo(dataSize + m_offsetInBuffer,
461 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
462 m_context.getDefaultAllocator(),
463 vk::MemoryRequirement::HostVisible);
464
465 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
466
467 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
468 deMemcpy(ptr + m_offsetInBuffer, &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
469
470 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
471
472 if (m_testIndirectCountExt)
473 {
474 m_offsetInCountBuffer = sizeof(tcu::Vec3);
475 m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
476 m_context.getDevice(),
477 BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
478 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
479 m_context.getDefaultAllocator(),
480 vk::MemoryRequirement::HostVisible);
481
482 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
483
484 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
485 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount;
486 else
487 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
488
489 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
490 }
491
492 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
493
494 if (m_drawType == DRAW_TYPE_INDEXED)
495 {
496 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
497 }
498
499 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
500 {
501 switch (m_drawType)
502 {
503 case DRAW_TYPE_SEQUENTIAL:
504 {
505 if (m_testIndirectCountExt)
506 m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
507 m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
508 m_strideInBuffer);
509 else
510 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
511 break;
512 }
513 case DRAW_TYPE_INDEXED:
514 {
515 if (m_testIndirectCountExt)
516 m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
517 m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
518 m_strideInBuffer);
519 else
520 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
521 break;
522 }
523 default:
524 TCU_FAIL("impossible");
525 }
526 }
527 else
528 {
529 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
530 {
531 switch (m_drawType)
532 {
533 case DRAW_TYPE_SEQUENTIAL:
534 {
535 if (m_testIndirectCountExt)
536 m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
537 m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
538 m_strideInBuffer);
539 else
540 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
541 break;
542 }
543 case DRAW_TYPE_INDEXED:
544 {
545 if (m_testIndirectCountExt)
546 m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
547 m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
548 m_strideInBuffer);
549 else
550 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
551 break;
552 }
553 default:
554 TCU_FAIL("impossible");
555 }
556 }
557 }
558 endRenderPass(m_vk, *m_cmdBuffer);
559 endCommandBuffer(m_vk, *m_cmdBuffer);
560
561 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
562
563 // Validation
564 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
565 referenceFrame.allocLevel(0);
566
567 const deInt32 frameWidth = referenceFrame.getWidth();
568 const deInt32 frameHeight = referenceFrame.getHeight();
569
570 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
571
572 ReferenceImageCoordinates refCoords;
573
574 for (int y = 0; y < frameHeight; y++)
575 {
576 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
577
578 for (int x = 0; x < frameWidth; x++)
579 {
580 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
581
582 if ((yCoord >= refCoords.bottom &&
583 yCoord <= refCoords.top &&
584 xCoord >= refCoords.left &&
585 xCoord <= refCoords.right))
586 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
587 }
588 }
589
590 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
591 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
592 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
593
594 qpTestResult res = QP_TEST_RESULT_PASS;
595
596 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
597 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
598 {
599 res = QP_TEST_RESULT_FAIL;
600 }
601
602 return tcu::TestStatus(res, qpGetTestResultName(res));
603 }
604
605 template<class FirstInstanceSupport>
IndirectDrawInstanced(Context & context,TestSpec testSpec)606 IndirectDrawInstanced<FirstInstanceSupport>::IndirectDrawInstanced (Context &context, TestSpec testSpec)
607 : IndirectDraw(context, testSpec)
608 {
609 if (!FirstInstanceSupport::isTestSupported(m_context.getDeviceFeatures()))
610 {
611 throw tcu::NotSupportedError("Required 'drawIndirectFirstInstance' feature is not supported");
612 }
613 }
614
615 template<class FirstInstanceSupport>
iterate(void)616 tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
617 {
618 tcu::TestLog& log = m_context.getTestContext().getLog();
619 const vk::VkQueue queue = m_context.getUniversalQueue();
620 const vk::VkDevice device = m_context.getDevice();
621
622 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
623 {
624 switch (m_topology)
625 {
626 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
627 {
628 vk::VkDrawIndirectCommand drawCmd[] =
629 {
630 {
631 3, //vertexCount
632 4, //instanceCount
633 2, //firstVertex
634 FirstInstanceSupport::getFirstInstance() //firstInstance
635 },
636 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
637 {
638 3, //vertexCount
639 4, //instanceCount
640 5, //firstVertex
641 FirstInstanceSupport::getFirstInstance() //firstInstance
642 }
643 };
644 addCommand(drawCmd[0]);
645 addCommand(drawCmd[1]);
646 addCommand(drawCmd[2]);
647 if (m_testIndirectCountExt)
648 {
649 addCommand(drawCmd[1]);
650 addCommand(drawCmd[1]);
651 }
652 break;
653 }
654 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
655 {
656 vk::VkDrawIndirectCommand drawCmd[] =
657 {
658 {
659 4, //vertexCount
660 4, //instanceCount
661 2, //firstVertex
662 FirstInstanceSupport::getFirstInstance() //firstInstance
663 },
664 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 },
665 {
666 4, //vertexCount
667 4, //instanceCount
668 6, //firstVertex
669 FirstInstanceSupport::getFirstInstance() //firstInstance
670 }
671 };
672 addCommand(drawCmd[0]);
673 addCommand(drawCmd[1]);
674 addCommand(drawCmd[2]);
675 if (m_testIndirectCountExt)
676 {
677 addCommand(drawCmd[1]);
678 addCommand(drawCmd[1]);
679 }
680 break;
681 }
682 default:
683 TCU_FAIL("impossible");
684 break;
685 }
686
687 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
688 }
689 else if (m_drawType == DRAW_TYPE_INDEXED)
690 {
691 switch (m_topology)
692 {
693 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
694 {
695 vk::VkDrawIndexedIndirectCommand drawCmd[] =
696 {
697 {
698 3, // indexCount
699 4, // instanceCount
700 2, // firstIndex
701 VERTEX_OFFSET, // vertexOffset
702 FirstInstanceSupport::getFirstInstance() // firstInstance
703 },
704 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
705 {
706 3, // indexCount
707 4, // instanceCount
708 5, // firstIndex
709 VERTEX_OFFSET, // vertexOffset
710 FirstInstanceSupport::getFirstInstance() // firstInstance
711 }
712 };
713 addCommand(drawCmd[0]);
714 addCommand(drawCmd[1]);
715 addCommand(drawCmd[2]);
716 if (m_testIndirectCountExt)
717 {
718 addCommand(drawCmd[1]);
719 addCommand(drawCmd[1]);
720 }
721 break;
722 }
723 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
724 {
725 vk::VkDrawIndexedIndirectCommand drawCmd[] =
726 {
727 {
728 4, // indexCount
729 4, // instanceCount
730 2, // firstIndex
731 VERTEX_OFFSET, // vertexOffset
732 FirstInstanceSupport::getFirstInstance() // firstInstance
733 },
734 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
735 {
736 4, // indexCount
737 4, // instanceCount
738 6, // firstIndex
739 VERTEX_OFFSET, // vertexOffset
740 FirstInstanceSupport::getFirstInstance() // firstInstance
741 }
742 };
743 addCommand(drawCmd[0]);
744 addCommand(drawCmd[1]);
745 addCommand(drawCmd[2]);
746 if (m_testIndirectCountExt)
747 {
748 addCommand(drawCmd[1]);
749 addCommand(drawCmd[1]);
750 }
751 break;
752 }
753 default:
754 TCU_FAIL("impossible");
755 break;
756 }
757
758 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
759 }
760
761 m_drawCount = 2;
762 m_offsetInBuffer = sizeof(m_junkData);
763
764 beginRenderPass();
765
766 const vk::VkDeviceSize vertexBufferOffset = 0;
767 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
768
769 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
770
771 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
772
773 m_indirectBuffer = Buffer::createAndAlloc( m_vk,
774 m_context.getDevice(),
775 BufferCreateInfo(dataSize + m_offsetInBuffer,
776 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
777 m_context.getDefaultAllocator(),
778 vk::MemoryRequirement::HostVisible);
779
780 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
781
782 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
783 deMemcpy((ptr + m_offsetInBuffer), &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
784
785 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
786
787 if (m_testIndirectCountExt)
788 {
789 m_offsetInCountBuffer = sizeof(tcu::Vec3);
790 m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
791 m_context.getDevice(),
792 BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
793 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
794 m_context.getDefaultAllocator(),
795 vk::MemoryRequirement::HostVisible);
796
797 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
798
799 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
800 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount;
801 else
802 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
803
804 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
805 }
806
807 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
808
809 if (m_drawType == DRAW_TYPE_INDEXED)
810 {
811 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
812 }
813
814 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
815 {
816 switch (m_drawType)
817 {
818 case DRAW_TYPE_SEQUENTIAL:
819 {
820 if (m_testIndirectCountExt)
821 m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
822 m_indirectCountBuffer->object(), m_offsetInCountBuffer,
823 m_drawCount + m_indirectCountExtDrawPadding, m_strideInBuffer);
824 else
825 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
826 break;
827 }
828 case DRAW_TYPE_INDEXED:
829 {
830 if (m_testIndirectCountExt)
831 m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
832 m_indirectCountBuffer->object(), m_offsetInCountBuffer,
833 m_drawCount + m_indirectCountExtDrawPadding, m_strideInBuffer);
834 else
835 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
836 break;
837 }
838 default:
839 TCU_FAIL("impossible");
840 }
841 }
842 else
843 {
844 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
845 {
846 switch (m_drawType)
847 {
848 case DRAW_TYPE_SEQUENTIAL:
849 {
850 if (m_testIndirectCountExt)
851 m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
852 m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
853 m_strideInBuffer);
854 else
855 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
856 break;
857 }
858 case DRAW_TYPE_INDEXED:
859 {
860 if (m_testIndirectCountExt)
861 m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
862 m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
863 m_strideInBuffer);
864 else
865 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
866 break;
867 }
868 default:
869 TCU_FAIL("impossible");
870 }
871 }
872 }
873 endRenderPass(m_vk, *m_cmdBuffer);
874 endCommandBuffer(m_vk, *m_cmdBuffer);
875
876 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
877
878 // Validation
879 VK_CHECK(m_vk.queueWaitIdle(queue));
880
881 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
882
883 referenceFrame.allocLevel(0);
884
885 const deInt32 frameWidth = referenceFrame.getWidth();
886 const deInt32 frameHeight = referenceFrame.getHeight();
887
888 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
889
890 ReferenceImageInstancedCoordinates refInstancedCoords;
891
892 for (int y = 0; y < frameHeight; y++)
893 {
894 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
895
896 for (int x = 0; x < frameWidth; x++)
897 {
898 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
899
900 if ((yCoord >= refInstancedCoords.bottom &&
901 yCoord <= refInstancedCoords.top &&
902 xCoord >= refInstancedCoords.left &&
903 xCoord <= refInstancedCoords.right))
904 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
905 }
906 }
907
908 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
909 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
910 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
911
912 qpTestResult res = QP_TEST_RESULT_PASS;
913
914 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
915 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
916 {
917 res = QP_TEST_RESULT_FAIL;
918 }
919
920 return tcu::TestStatus(res, qpGetTestResultName(res));
921 }
922
923 } // anonymous
924
IndirectDrawTests(tcu::TestContext & testCtx)925 IndirectDrawTests::IndirectDrawTests (tcu::TestContext& testCtx)
926 : TestCaseGroup(testCtx, "indirect_draw", "indirect drawing simple geometry")
927 {
928 /* Left blank on purpose */
929 }
930
~IndirectDrawTests(void)931 IndirectDrawTests::~IndirectDrawTests (void) {}
932
933
init(void)934 void IndirectDrawTests::init (void)
935 {
936 for (int drawTypeIdx = 0; drawTypeIdx < DRAWTYPE_LAST; drawTypeIdx++)
937 {
938 std::string drawTypeStr;
939 switch (drawTypeIdx)
940 {
941 case DRAW_TYPE_SEQUENTIAL:
942 drawTypeStr = "sequential";
943 break;
944 case DRAW_TYPE_INDEXED:
945 drawTypeStr = "indexed";
946 break;
947 default:
948 TCU_FAIL("impossible");
949 }
950
951 tcu::TestCaseGroup* drawTypeGroup = new tcu::TestCaseGroup(m_testCtx, drawTypeStr.c_str(), ("Draws geometry using " + drawTypeStr + "draw call").c_str());
952 {
953 tcu::TestCaseGroup* indirectDrawGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw", "Draws geometry");
954 tcu::TestCaseGroup* indirectDrawCountGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count", "Draws geometry with VK_KHR_draw_indirect_count extension");
955 {
956 IndirectDraw::TestSpec testSpec;
957 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
958 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetch.vert";
959 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
960 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
961 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
962 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
963 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
964
965 testSpec.testIndirectCountExt = true;
966 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
967 indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
968 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
969 indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
970 }
971 drawTypeGroup->addChild(indirectDrawGroup);
972 drawTypeGroup->addChild(indirectDrawCountGroup);
973
974 {
975 tcu::TestCaseGroup* indirectDrawFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_first_instance", "Draws geometry with different first instance in one commandbuffer");
976 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 ");
977 {
978 IndirectDraw::TestSpec testSpec;
979 testSpec.testFirstInstanceNdx = true;
980 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
981 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanceIndex.vert";
982 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
983 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
984 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
985 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
986 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
987
988 testSpec.testIndirectCountExt = true;
989 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
990 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
991 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
992 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
993 }
994 drawTypeGroup->addChild(indirectDrawFirstInstanceGroup);
995 drawTypeGroup->addChild(indirectDrawCountFirstInstanceGroup);
996 }
997
998 tcu::TestCaseGroup* indirectDrawInstancedGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_instanced", "Draws an instanced geometry");
999 tcu::TestCaseGroup* indirectDrawCountInstancedGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count_instanced", "Draws an instanced geometry with VK_KHR_draw_indirect_count extension");
1000 {
1001 tcu::TestCaseGroup* indirectDrawNoFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1002 tcu::TestCaseGroup* indirectDrawCountNoFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1003 {
1004 IndirectDrawInstanced<FirstInstanceNotSupported>::TestSpec testSpec;
1005 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1006
1007 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanced.vert";
1008 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1009
1010 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1011 indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1012 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1013 indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1014
1015 testSpec.testIndirectCountExt = true;
1016 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1017 indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1018 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1019 indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1020 }
1021 indirectDrawInstancedGroup->addChild(indirectDrawNoFirstInstanceGroup);
1022 indirectDrawCountInstancedGroup->addChild(indirectDrawCountNoFirstInstanceGroup);
1023
1024 tcu::TestCaseGroup* indirectDrawFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1025 tcu::TestCaseGroup* indirectDrawCountFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1026 {
1027 IndirectDrawInstanced<FirstInstanceSupported>::TestSpec testSpec;
1028 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1029
1030 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
1031 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1032
1033 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1034 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1035 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1036 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1037
1038 testSpec.testIndirectCountExt = true;
1039 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1040 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1041 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1042 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1043 }
1044 indirectDrawInstancedGroup->addChild(indirectDrawFirstInstanceGroup);
1045 indirectDrawCountInstancedGroup->addChild(indirectDrawCountFirstInstanceGroup);
1046 }
1047 drawTypeGroup->addChild(indirectDrawInstancedGroup);
1048 drawTypeGroup->addChild(indirectDrawCountInstancedGroup);
1049 }
1050
1051 addChild(drawTypeGroup);
1052 }
1053 }
1054
1055 } // DrawTests
1056 } // vkt
1057