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