1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Draw Indirect Test
23 *//*--------------------------------------------------------------------*/
25 #include "vktDrawIndirectTest.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktDrawTestCaseUtil.hpp"
30 #include "vktDrawBaseClass.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuResource.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuRGBA.hpp"
37 #include "vkQueryUtil.hpp"
40 #include "vkCmdUtil.hpp"
73 enum class IndirectCountType
82 struct DrawTypedTestSpec : public TestSpecBase
85 : testFirstInstanceNdx(false)
86 , testIndirectCountExt(IndirectCountType::NONE)
90 bool testFirstInstanceNdx;
91 IndirectCountType testIndirectCountExt;
94 class IndirectDraw : public DrawTestsBaseClass
97 typedef DrawTypedTestSpec TestSpec;
99 IndirectDraw (Context &context, TestSpec testSpec);
100 virtual tcu::TestStatus iterate (void);
102 template<typename T> void addCommand (const T&);
105 void setVertexBuffer (void);
106 void setFirstInstanceVertexBuffer (void);
108 std::vector<char> m_indirectBufferContents;
109 de::SharedPtr<Buffer> m_indirectBuffer;
110 vk::VkDeviceSize m_offsetInBuffer;
111 deUint32 m_strideInBuffer;
113 const IndirectCountType m_testIndirectCountExt;
114 de::SharedPtr<Buffer> m_indirectCountBuffer;
115 vk::VkDeviceSize m_offsetInCountBuffer;
116 const deUint32 m_indirectCountExtDrawPadding;
118 deUint32 m_drawCount;
121 const DrawType m_drawType;
122 const bool m_testFirstInstanceNdx;
123 deBool m_isMultiDrawEnabled;
124 deUint32 m_drawIndirectMaxCount;
126 de::SharedPtr<Buffer> m_indexBuffer;
129 struct FirstInstanceSupported
131 static deUint32 getFirstInstance (void) { return 2; }
132 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures& features) { return features.drawIndirectFirstInstance == VK_TRUE; }
135 struct FirstInstanceNotSupported
137 static deUint32 getFirstInstance (void) { return 0; }
138 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures&) { return true; }
141 template<class FirstInstanceSupport>
142 class IndirectDrawInstanced : public IndirectDraw
145 IndirectDrawInstanced (Context &context, TestSpec testSpec);
146 virtual tcu::TestStatus iterate (void);
149 void IndirectDraw::setVertexBuffer (void)
151 int refVertexIndex = 2;
153 if (m_drawType == DRAW_TYPE_INDEXED)
155 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
157 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
159 refVertexIndex += VERTEX_OFFSET;
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));
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++));
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++));
186 DE_FATAL("Unknown topology");
190 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
193 void IndirectDraw::setFirstInstanceVertexBuffer (void)
195 if (m_context.getDeviceFeatures().drawIndirectFirstInstance != VK_TRUE)
197 TCU_THROW(NotSupportedError, "Required 'drawIndirectFirstInstance' feature is not supported");
200 if (m_drawType == DRAW_TYPE_INDEXED)
202 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
204 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
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));
213 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
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));
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));
226 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
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));
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));
242 DE_FATAL("Unknown topology");
246 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
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)
256 if (m_testFirstInstanceNdx)
257 setFirstInstanceVertexBuffer();
263 if (testSpec.drawType == DRAW_TYPE_INDEXED)
265 const size_t indexBufferLength = m_data.size() - VERTEX_OFFSET;
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++)
271 indices[i] = static_cast<deUint32>(i);
273 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
276 // Check device for multidraw support:
277 if (!m_context.getDeviceFeatures().multiDrawIndirect || m_testFirstInstanceNdx)
278 m_isMultiDrawEnabled = false;
280 m_isMultiDrawEnabled = true;
282 m_drawIndirectMaxCount = m_context.getDeviceProperties().limits.maxDrawIndirectCount;
286 void IndirectDraw::addCommand<vk::VkDrawIndirectCommand> (const vk::VkDrawIndirectCommand& command)
288 DE_ASSERT(m_drawType == DRAW_TYPE_SEQUENTIAL);
290 const size_t currentSize = m_indirectBufferContents.size();
292 m_indirectBufferContents.resize(currentSize + sizeof(command));
294 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
298 void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand> (const vk::VkDrawIndexedIndirectCommand& command)
300 DE_ASSERT(m_drawType == DRAW_TYPE_INDEXED);
302 const size_t currentSize = m_indirectBufferContents.size();
304 m_indirectBufferContents.resize(currentSize + sizeof(command));
306 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
309 tcu::TestStatus IndirectDraw::iterate (void)
311 tcu::TestLog& log = m_context.getTestContext().getLog();
312 const vk::VkQueue queue = m_context.getUniversalQueue();
313 const vk::VkDevice device = m_context.getDevice();
316 m_offsetInBuffer = sizeof(m_junkData);
317 const deUint32 m_bufferDrawCount = 2u * m_drawCount;
319 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
323 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
325 vk::VkDrawIndirectCommand drawCommands[] =
331 (m_testFirstInstanceNdx ? 1u : 0u) //firstInstance
333 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
341 addCommand(drawCommands[0]);
342 addCommand(drawCommands[1]);
343 addCommand(drawCommands[2]);
344 addCommand(drawCommands[1]);
345 if (m_testIndirectCountExt != IndirectCountType::NONE)
347 // Add padding data to the buffer to make sure it's large enough.
348 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
350 addCommand(drawCommands[1]);
351 addCommand(drawCommands[1]);
356 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
358 vk::VkDrawIndirectCommand drawCommands[] =
364 (m_testFirstInstanceNdx ? 1u : 0u) //firstInstance
366 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
374 addCommand(drawCommands[0]);
375 addCommand(drawCommands[1]);
376 addCommand(drawCommands[2]);
377 addCommand(drawCommands[1]);
378 if (m_testIndirectCountExt != IndirectCountType::NONE)
380 // Add padding data to the buffer to make sure it's large enough.
381 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
383 addCommand(drawCommands[1]);
384 addCommand(drawCommands[1]);
390 TCU_FAIL("impossible");
393 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
395 else if (m_drawType == DRAW_TYPE_INDEXED)
399 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
401 vk::VkDrawIndexedIndirectCommand drawCommands[] =
407 VERTEX_OFFSET, // vertexOffset
408 (m_testFirstInstanceNdx ? 1u : 0u), // firstInstance
410 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
415 VERTEX_OFFSET, // vertexOffset
419 addCommand(drawCommands[0]);
420 addCommand(drawCommands[1]);
421 addCommand(drawCommands[2]);
422 addCommand(drawCommands[1]);
423 if (m_testIndirectCountExt != IndirectCountType::NONE)
425 // Add padding data to the buffer to make sure it's large enough.
426 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
428 addCommand(drawCommands[1]);
429 addCommand(drawCommands[1]);
434 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
436 vk::VkDrawIndexedIndirectCommand drawCommands[] =
442 VERTEX_OFFSET, // vertexOffset
443 (m_testFirstInstanceNdx ? 1u : 0u), // firstInstance
445 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
450 VERTEX_OFFSET, // vertexOffset
454 addCommand(drawCommands[0]);
455 addCommand(drawCommands[1]);
456 addCommand(drawCommands[2]);
457 addCommand(drawCommands[1]);
458 if (m_testIndirectCountExt != IndirectCountType::NONE)
460 // Add padding data to the buffer to make sure it's large enough.
461 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
463 addCommand(drawCommands[1]);
464 addCommand(drawCommands[1]);
470 TCU_FAIL("impossible");
473 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
478 const vk::VkDeviceSize vertexBufferOffset = 0;
479 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
481 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
483 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
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);
492 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
494 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
495 deMemcpy(ptr + m_offsetInBuffer, &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
497 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
499 if (m_testIndirectCountExt != IndirectCountType::NONE)
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);
509 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
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);
515 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? 1u : m_drawCount + m_indirectCountExtDrawPadding);
517 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
520 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
522 if (m_drawType == DRAW_TYPE_INDEXED)
524 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
527 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
531 case DRAW_TYPE_SEQUENTIAL:
533 if (m_testIndirectCountExt != IndirectCountType::NONE)
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,
541 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
544 case DRAW_TYPE_INDEXED:
546 if (m_testIndirectCountExt != IndirectCountType::NONE)
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,
554 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
558 TCU_FAIL("impossible");
563 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
567 case DRAW_TYPE_SEQUENTIAL:
569 if (m_testIndirectCountExt != IndirectCountType::NONE)
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,
577 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
580 case DRAW_TYPE_INDEXED:
582 if (m_testIndirectCountExt != IndirectCountType::NONE)
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,
590 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
594 TCU_FAIL("impossible");
598 endRenderPass(m_vk, *m_cmdBuffer);
599 endCommandBuffer(m_vk, *m_cmdBuffer);
601 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
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);
607 const deInt32 frameWidth = referenceFrame.getWidth();
608 const deInt32 frameHeight = referenceFrame.getHeight();
610 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
612 ReferenceImageCoordinates refCoords;
614 for (int y = 0; y < frameHeight; y++)
616 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
618 for (int x = 0; x < frameWidth; x++)
620 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
634 qpTestResult res = QP_TEST_RESULT_PASS;
636 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
637 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
639 res = QP_TEST_RESULT_FAIL;
642 return tcu::TestStatus(res, qpGetTestResultName(res));
645 template<class FirstInstanceSupport>
646 IndirectDrawInstanced<FirstInstanceSupport>::IndirectDrawInstanced (Context &context, TestSpec testSpec)
647 : IndirectDraw(context, testSpec)
649 if (!FirstInstanceSupport::isTestSupported(m_context.getDeviceFeatures()))
651 throw tcu::NotSupportedError("Required 'drawIndirectFirstInstance' feature is not supported");
655 template<class FirstInstanceSupport>
656 tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
658 tcu::TestLog& log = m_context.getTestContext().getLog();
659 const vk::VkQueue queue = m_context.getUniversalQueue();
660 const vk::VkDevice device = m_context.getDevice();
663 m_offsetInBuffer = sizeof(m_junkData);
664 const deUint32 m_bufferDrawCount = 2u * m_drawCount;
666 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
670 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
672 vk::VkDrawIndirectCommand drawCmd[] =
678 FirstInstanceSupport::getFirstInstance() //firstInstance
680 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
685 FirstInstanceSupport::getFirstInstance() //firstInstance
688 addCommand(drawCmd[0]);
689 addCommand(drawCmd[1]);
690 addCommand(drawCmd[2]);
691 if (m_testIndirectCountExt != IndirectCountType::NONE)
693 // Add padding data to the buffer to make sure it's large enough.
694 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
696 addCommand(drawCmd[1]);
697 addCommand(drawCmd[1]);
702 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
704 vk::VkDrawIndirectCommand drawCmd[] =
710 FirstInstanceSupport::getFirstInstance() //firstInstance
712 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 },
717 FirstInstanceSupport::getFirstInstance() //firstInstance
720 addCommand(drawCmd[0]);
721 addCommand(drawCmd[1]);
722 addCommand(drawCmd[2]);
723 if (m_testIndirectCountExt != IndirectCountType::NONE)
725 // Add padding data to the buffer to make sure it's large enough.
726 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
728 addCommand(drawCmd[1]);
729 addCommand(drawCmd[1]);
735 TCU_FAIL("impossible");
739 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
741 else if (m_drawType == DRAW_TYPE_INDEXED)
745 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
747 vk::VkDrawIndexedIndirectCommand drawCmd[] =
753 VERTEX_OFFSET, // vertexOffset
754 FirstInstanceSupport::getFirstInstance() // firstInstance
756 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
761 VERTEX_OFFSET, // vertexOffset
762 FirstInstanceSupport::getFirstInstance() // firstInstance
765 addCommand(drawCmd[0]);
766 addCommand(drawCmd[1]);
767 addCommand(drawCmd[2]);
768 if (m_testIndirectCountExt != IndirectCountType::NONE)
770 // Add padding data to the buffer to make sure it's large enough.
771 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
773 addCommand(drawCmd[1]);
774 addCommand(drawCmd[1]);
779 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
781 vk::VkDrawIndexedIndirectCommand drawCmd[] =
787 VERTEX_OFFSET, // vertexOffset
788 FirstInstanceSupport::getFirstInstance() // firstInstance
790 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
795 VERTEX_OFFSET, // vertexOffset
796 FirstInstanceSupport::getFirstInstance() // firstInstance
799 addCommand(drawCmd[0]);
800 addCommand(drawCmd[1]);
801 addCommand(drawCmd[2]);
802 if (m_testIndirectCountExt != IndirectCountType::NONE)
804 // Add padding data to the buffer to make sure it's large enough.
805 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
807 addCommand(drawCmd[1]);
808 addCommand(drawCmd[1]);
814 TCU_FAIL("impossible");
818 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
823 const vk::VkDeviceSize vertexBufferOffset = 0;
824 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
826 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
828 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
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);
837 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
839 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
840 deMemcpy((ptr + m_offsetInBuffer), &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
842 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
844 if (m_testIndirectCountExt != IndirectCountType::NONE)
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);
854 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
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);
860 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
862 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
865 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
867 if (m_drawType == DRAW_TYPE_INDEXED)
869 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
872 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
876 case DRAW_TYPE_SEQUENTIAL:
878 if (m_testIndirectCountExt != IndirectCountType::NONE)
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);
886 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
889 case DRAW_TYPE_INDEXED:
891 if (m_testIndirectCountExt != IndirectCountType::NONE)
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);
899 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
903 TCU_FAIL("impossible");
908 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
912 case DRAW_TYPE_SEQUENTIAL:
914 if (m_testIndirectCountExt != IndirectCountType::NONE)
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,
922 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
925 case DRAW_TYPE_INDEXED:
927 if (m_testIndirectCountExt != IndirectCountType::NONE)
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,
935 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
939 TCU_FAIL("impossible");
943 endRenderPass(m_vk, *m_cmdBuffer);
944 endCommandBuffer(m_vk, *m_cmdBuffer);
946 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
949 VK_CHECK(m_vk.queueWaitIdle(queue));
951 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5 + static_cast<float>(HEIGHT)));
953 referenceFrame.allocLevel(0);
955 const deInt32 frameWidth = referenceFrame.getWidth();
956 const deInt32 frameHeight = referenceFrame.getHeight();
958 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
960 ReferenceImageInstancedCoordinates refInstancedCoords;
962 for (int y = 0; y < frameHeight; y++)
964 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
966 for (int x = 0; x < frameWidth; x++)
968 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
982 qpTestResult res = QP_TEST_RESULT_PASS;
984 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
985 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
987 res = QP_TEST_RESULT_FAIL;
990 return tcu::TestStatus(res, qpGetTestResultName(res));
993 void checkIndirectCountExt (Context& context)
995 context.requireDeviceFunctionality("VK_KHR_draw_indirect_count");
1000 IndirectDrawTests::IndirectDrawTests (tcu::TestContext& testCtx)
1001 : TestCaseGroup(testCtx, "indirect_draw", "indirect drawing simple geometry")
1003 /* Left blank on purpose */
1006 IndirectDrawTests::~IndirectDrawTests (void) {}
1009 void IndirectDrawTests::init (void)
1011 for (int drawTypeIdx = 0; drawTypeIdx < DRAWTYPE_LAST; drawTypeIdx++)
1013 std::string drawTypeStr;
1014 switch (drawTypeIdx)
1016 case DRAW_TYPE_SEQUENTIAL:
1017 drawTypeStr = "sequential";
1019 case DRAW_TYPE_INDEXED:
1020 drawTypeStr = "indexed";
1023 TCU_FAIL("impossible");
1026 tcu::TestCaseGroup* drawTypeGroup = new tcu::TestCaseGroup(m_testCtx, drawTypeStr.c_str(), ("Draws geometry using " + drawTypeStr + "draw call").c_str());
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");
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));
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)));
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)));
1053 drawTypeGroup->addChild(indirectDrawGroup);
1054 drawTypeGroup->addChild(indirectDrawCountGroup);
1055 drawTypeGroup->addChild(indirectDrawParamCountGroup);
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");
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));
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)));
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)));
1084 drawTypeGroup->addChild(indirectDrawFirstInstanceGroup);
1085 drawTypeGroup->addChild(indirectDrawCountFirstInstanceGroup);
1086 drawTypeGroup->addChild(indirectDrawParamCountFirstInstanceGroup);
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");
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");
1097 IndirectDrawInstanced<FirstInstanceNotSupported>::TestSpec testSpec;
1098 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1100 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanced.vert";
1101 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
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));
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)));
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)));
1120 indirectDrawInstancedGroup->addChild(indirectDrawNoFirstInstanceGroup);
1121 indirectDrawCountInstancedGroup->addChild(indirectDrawCountNoFirstInstanceGroup);
1122 indirectDrawParamCountInstancedGroup->addChild(indirectDrawParamCountNoFirstInstanceGroup);
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");
1128 IndirectDrawInstanced<FirstInstanceSupported>::TestSpec testSpec;
1129 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1131 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
1132 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
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));
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)));
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)));
1151 indirectDrawInstancedGroup->addChild(indirectDrawFirstInstanceGroup);
1152 indirectDrawCountInstancedGroup->addChild(indirectDrawCountFirstInstanceGroup);
1153 indirectDrawParamCountInstancedGroup->addChild(indirectDrawParamCountFirstInstanceGroup);
1155 drawTypeGroup->addChild(indirectDrawInstancedGroup);
1156 drawTypeGroup->addChild(indirectDrawCountInstancedGroup);
1157 drawTypeGroup->addChild(indirectDrawParamCountInstancedGroup);
1160 addChild(drawTypeGroup);