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 : drawType(DRAWTYPE_LAST)
86 , testFirstInstanceNdx(false)
87 , testIndirectCountExt(IndirectCountType::NONE)
91 bool testFirstInstanceNdx;
92 IndirectCountType testIndirectCountExt;
95 class IndirectDraw : public DrawTestsBaseClass
98 typedef DrawTypedTestSpec TestSpec;
100 IndirectDraw (Context &context, TestSpec testSpec);
101 virtual tcu::TestStatus iterate (void);
103 template<typename T> void addCommand (const T&);
106 void setVertexBuffer (void);
107 void setFirstInstanceVertexBuffer (void);
109 std::vector<char> m_indirectBufferContents;
110 de::SharedPtr<Buffer> m_indirectBuffer;
111 vk::VkDeviceSize m_offsetInBuffer;
112 deUint32 m_strideInBuffer;
114 const IndirectCountType m_testIndirectCountExt;
115 de::SharedPtr<Buffer> m_indirectCountBuffer;
116 vk::VkDeviceSize m_offsetInCountBuffer;
117 const deUint32 m_indirectCountExtDrawPadding;
119 deUint32 m_drawCount;
122 const DrawType m_drawType;
123 const bool m_testFirstInstanceNdx;
124 deBool m_isMultiDrawEnabled;
125 deUint32 m_drawIndirectMaxCount;
127 de::SharedPtr<Buffer> m_indexBuffer;
130 struct FirstInstanceSupported
132 static deUint32 getFirstInstance (void) { return 2; }
133 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures& features) { return features.drawIndirectFirstInstance == VK_TRUE; }
136 struct FirstInstanceNotSupported
138 static deUint32 getFirstInstance (void) { return 0; }
139 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures&) { return true; }
142 template<class FirstInstanceSupport>
143 class IndirectDrawInstanced : public IndirectDraw
146 IndirectDrawInstanced (Context &context, TestSpec testSpec);
147 virtual tcu::TestStatus iterate (void);
150 void IndirectDraw::setVertexBuffer (void)
152 int refVertexIndex = 2;
154 if (m_drawType == DRAW_TYPE_INDEXED)
156 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
158 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
160 refVertexIndex += VERTEX_OFFSET;
163 m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
164 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
168 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
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 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
176 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
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.0f, 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.3f, 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 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
187 DE_FATAL("Unknown topology");
191 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
194 void IndirectDraw::setFirstInstanceVertexBuffer (void)
196 if (m_context.getDeviceFeatures().drawIndirectFirstInstance != VK_TRUE)
198 TCU_THROW(NotSupportedError, "Required 'drawIndirectFirstInstance' feature is not supported");
201 if (m_drawType == DRAW_TYPE_INDEXED)
203 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
205 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 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
214 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
216 int refInstanceIndex = 1;
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 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
221 refInstanceIndex = 0;
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 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
227 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
229 int refInstanceIndex = 1;
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.0f, 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 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
235 refInstanceIndex = 0;
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.3f, 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 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
243 DE_FATAL("Unknown topology");
247 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
250 IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
251 : DrawTestsBaseClass (context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
252 , m_testIndirectCountExt (testSpec.testIndirectCountExt)
253 , m_indirectCountExtDrawPadding (1u)
254 , m_drawType (testSpec.drawType)
255 , m_testFirstInstanceNdx (testSpec.testFirstInstanceNdx)
257 if (m_testFirstInstanceNdx)
258 setFirstInstanceVertexBuffer();
264 if (testSpec.drawType == DRAW_TYPE_INDEXED)
266 const size_t indexBufferLength = m_data.size() - VERTEX_OFFSET;
268 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);
269 deUint32* indices = reinterpret_cast<deUint32*>(m_indexBuffer->getBoundMemory().getHostPtr());
270 for (size_t i = 0; i < indexBufferLength; i++)
272 indices[i] = static_cast<deUint32>(i);
274 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
277 // Check device for multidraw support:
278 if (!m_context.getDeviceFeatures().multiDrawIndirect || m_testFirstInstanceNdx)
279 m_isMultiDrawEnabled = false;
281 m_isMultiDrawEnabled = true;
283 m_drawIndirectMaxCount = m_context.getDeviceProperties().limits.maxDrawIndirectCount;
287 void IndirectDraw::addCommand<vk::VkDrawIndirectCommand> (const vk::VkDrawIndirectCommand& command)
289 DE_ASSERT(m_drawType == DRAW_TYPE_SEQUENTIAL);
291 const size_t currentSize = m_indirectBufferContents.size();
293 m_indirectBufferContents.resize(currentSize + sizeof(command));
295 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
299 void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand> (const vk::VkDrawIndexedIndirectCommand& command)
301 DE_ASSERT(m_drawType == DRAW_TYPE_INDEXED);
303 const size_t currentSize = m_indirectBufferContents.size();
305 m_indirectBufferContents.resize(currentSize + sizeof(command));
307 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
310 tcu::TestStatus IndirectDraw::iterate (void)
312 tcu::TestLog& log = m_context.getTestContext().getLog();
313 const vk::VkQueue queue = m_context.getUniversalQueue();
314 const vk::VkDevice device = m_context.getDevice();
317 m_offsetInBuffer = sizeof(m_junkData);
318 const deUint32 m_bufferDrawCount = 2u * m_drawCount;
320 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
324 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
326 vk::VkDrawIndirectCommand drawCommands[] =
332 (m_testFirstInstanceNdx ? 1u : 0u) //firstInstance
334 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
342 addCommand(drawCommands[0]);
343 addCommand(drawCommands[1]);
344 addCommand(drawCommands[2]);
345 addCommand(drawCommands[1]);
346 if (m_testIndirectCountExt != IndirectCountType::NONE)
348 // Add padding data to the buffer to make sure it's large enough.
349 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
351 addCommand(drawCommands[1]);
352 addCommand(drawCommands[1]);
357 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
359 vk::VkDrawIndirectCommand drawCommands[] =
365 (m_testFirstInstanceNdx ? 1u : 0u) //firstInstance
367 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
375 addCommand(drawCommands[0]);
376 addCommand(drawCommands[1]);
377 addCommand(drawCommands[2]);
378 addCommand(drawCommands[1]);
379 if (m_testIndirectCountExt != IndirectCountType::NONE)
381 // Add padding data to the buffer to make sure it's large enough.
382 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
384 addCommand(drawCommands[1]);
385 addCommand(drawCommands[1]);
391 TCU_FAIL("impossible");
394 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
396 else if (m_drawType == DRAW_TYPE_INDEXED)
400 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
402 vk::VkDrawIndexedIndirectCommand drawCommands[] =
408 VERTEX_OFFSET, // vertexOffset
409 (m_testFirstInstanceNdx ? 1u : 0u), // firstInstance
411 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
416 VERTEX_OFFSET, // vertexOffset
420 addCommand(drawCommands[0]);
421 addCommand(drawCommands[1]);
422 addCommand(drawCommands[2]);
423 addCommand(drawCommands[1]);
424 if (m_testIndirectCountExt != IndirectCountType::NONE)
426 // Add padding data to the buffer to make sure it's large enough.
427 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
429 addCommand(drawCommands[1]);
430 addCommand(drawCommands[1]);
435 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
437 vk::VkDrawIndexedIndirectCommand drawCommands[] =
443 VERTEX_OFFSET, // vertexOffset
444 (m_testFirstInstanceNdx ? 1u : 0u), // firstInstance
446 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
451 VERTEX_OFFSET, // vertexOffset
455 addCommand(drawCommands[0]);
456 addCommand(drawCommands[1]);
457 addCommand(drawCommands[2]);
458 addCommand(drawCommands[1]);
459 if (m_testIndirectCountExt != IndirectCountType::NONE)
461 // Add padding data to the buffer to make sure it's large enough.
462 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
464 addCommand(drawCommands[1]);
465 addCommand(drawCommands[1]);
471 TCU_FAIL("impossible");
474 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
479 const vk::VkDeviceSize vertexBufferOffset = 0;
480 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
482 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
484 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
486 m_indirectBuffer = Buffer::createAndAlloc( m_vk,
487 m_context.getDevice(),
488 BufferCreateInfo(dataSize + m_offsetInBuffer,
489 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
490 m_context.getDefaultAllocator(),
491 vk::MemoryRequirement::HostVisible);
493 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
495 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
496 deMemcpy(ptr + m_offsetInBuffer, &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
498 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
500 if (m_testIndirectCountExt != IndirectCountType::NONE)
502 m_offsetInCountBuffer = sizeof(tcu::Vec3);
503 m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
504 m_context.getDevice(),
505 BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
506 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
507 m_context.getDefaultAllocator(),
508 vk::MemoryRequirement::HostVisible);
510 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
512 // For IndirectCountType::PARAM_LIMIT, the real limit will be set using the call parameter.
513 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
514 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount + (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? 0u : m_indirectCountExtDrawPadding);
516 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? 1u : m_drawCount + m_indirectCountExtDrawPadding);
518 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
521 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
523 if (m_drawType == DRAW_TYPE_INDEXED)
525 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
528 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
532 case DRAW_TYPE_SEQUENTIAL:
534 if (m_testIndirectCountExt != IndirectCountType::NONE)
536 const deUint32 maxDrawCount = m_drawCount + (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_indirectCountExtDrawPadding : 0u);
537 m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
538 m_indirectCountBuffer->object(), m_offsetInCountBuffer, maxDrawCount,
542 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
545 case DRAW_TYPE_INDEXED:
547 if (m_testIndirectCountExt != IndirectCountType::NONE)
549 const deUint32 maxDrawCount = m_drawCount + (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_indirectCountExtDrawPadding : 0u);
550 m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
551 m_indirectCountBuffer->object(), m_offsetInCountBuffer, maxDrawCount,
555 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
559 TCU_FAIL("impossible");
564 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
568 case DRAW_TYPE_SEQUENTIAL:
570 if (m_testIndirectCountExt != IndirectCountType::NONE)
572 const deUint32 maxDrawCount = (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_drawCount + m_indirectCountExtDrawPadding : 1u);
573 m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
574 m_indirectCountBuffer->object(), m_offsetInCountBuffer, maxDrawCount,
578 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
581 case DRAW_TYPE_INDEXED:
583 if (m_testIndirectCountExt != IndirectCountType::NONE)
585 const deUint32 maxDrawCount = (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_drawCount + m_indirectCountExtDrawPadding : 1u);
586 m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
587 m_indirectCountBuffer->object(), m_offsetInCountBuffer, maxDrawCount,
591 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
595 TCU_FAIL("impossible");
599 endRenderPass(m_vk, *m_cmdBuffer);
600 endCommandBuffer(m_vk, *m_cmdBuffer);
602 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
605 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
606 referenceFrame.allocLevel(0);
608 const deInt32 frameWidth = referenceFrame.getWidth();
609 const deInt32 frameHeight = referenceFrame.getHeight();
611 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
613 ReferenceImageCoordinates refCoords;
615 for (int y = 0; y < frameHeight; y++)
617 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
619 for (int x = 0; x < frameWidth; x++)
621 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
623 if ((yCoord >= refCoords.bottom &&
624 yCoord <= refCoords.top &&
625 xCoord >= refCoords.left &&
626 xCoord <= refCoords.right))
627 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
631 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
632 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
633 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
635 qpTestResult res = QP_TEST_RESULT_PASS;
637 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
638 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
640 res = QP_TEST_RESULT_FAIL;
643 return tcu::TestStatus(res, qpGetTestResultName(res));
646 template<class FirstInstanceSupport>
647 IndirectDrawInstanced<FirstInstanceSupport>::IndirectDrawInstanced (Context &context, TestSpec testSpec)
648 : IndirectDraw(context, testSpec)
650 if (!FirstInstanceSupport::isTestSupported(m_context.getDeviceFeatures()))
652 throw tcu::NotSupportedError("Required 'drawIndirectFirstInstance' feature is not supported");
656 template<class FirstInstanceSupport>
657 tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
659 tcu::TestLog& log = m_context.getTestContext().getLog();
660 const vk::VkQueue queue = m_context.getUniversalQueue();
661 const vk::VkDevice device = m_context.getDevice();
664 m_offsetInBuffer = sizeof(m_junkData);
665 const deUint32 m_bufferDrawCount = 2u * m_drawCount;
667 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
671 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
673 vk::VkDrawIndirectCommand drawCmd[] =
679 FirstInstanceSupport::getFirstInstance() //firstInstance
681 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
686 FirstInstanceSupport::getFirstInstance() //firstInstance
689 addCommand(drawCmd[0]);
690 addCommand(drawCmd[1]);
691 addCommand(drawCmd[2]);
692 if (m_testIndirectCountExt != IndirectCountType::NONE)
694 // Add padding data to the buffer to make sure it's large enough.
695 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
697 addCommand(drawCmd[1]);
698 addCommand(drawCmd[1]);
703 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
705 vk::VkDrawIndirectCommand drawCmd[] =
711 FirstInstanceSupport::getFirstInstance() //firstInstance
713 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 },
718 FirstInstanceSupport::getFirstInstance() //firstInstance
721 addCommand(drawCmd[0]);
722 addCommand(drawCmd[1]);
723 addCommand(drawCmd[2]);
724 if (m_testIndirectCountExt != IndirectCountType::NONE)
726 // Add padding data to the buffer to make sure it's large enough.
727 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
729 addCommand(drawCmd[1]);
730 addCommand(drawCmd[1]);
736 TCU_FAIL("impossible");
740 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
742 else if (m_drawType == DRAW_TYPE_INDEXED)
746 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
748 vk::VkDrawIndexedIndirectCommand drawCmd[] =
754 VERTEX_OFFSET, // vertexOffset
755 FirstInstanceSupport::getFirstInstance() // firstInstance
757 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
762 VERTEX_OFFSET, // vertexOffset
763 FirstInstanceSupport::getFirstInstance() // firstInstance
766 addCommand(drawCmd[0]);
767 addCommand(drawCmd[1]);
768 addCommand(drawCmd[2]);
769 if (m_testIndirectCountExt != IndirectCountType::NONE)
771 // Add padding data to the buffer to make sure it's large enough.
772 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
774 addCommand(drawCmd[1]);
775 addCommand(drawCmd[1]);
780 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
782 vk::VkDrawIndexedIndirectCommand drawCmd[] =
788 VERTEX_OFFSET, // vertexOffset
789 FirstInstanceSupport::getFirstInstance() // firstInstance
791 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
796 VERTEX_OFFSET, // vertexOffset
797 FirstInstanceSupport::getFirstInstance() // firstInstance
800 addCommand(drawCmd[0]);
801 addCommand(drawCmd[1]);
802 addCommand(drawCmd[2]);
803 if (m_testIndirectCountExt != IndirectCountType::NONE)
805 // Add padding data to the buffer to make sure it's large enough.
806 for (deUint32 i = 0; i < m_bufferDrawCount; ++i)
808 addCommand(drawCmd[1]);
809 addCommand(drawCmd[1]);
815 TCU_FAIL("impossible");
819 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
824 const vk::VkDeviceSize vertexBufferOffset = 0;
825 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
827 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
829 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
831 m_indirectBuffer = Buffer::createAndAlloc( m_vk,
832 m_context.getDevice(),
833 BufferCreateInfo(dataSize + m_offsetInBuffer,
834 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
835 m_context.getDefaultAllocator(),
836 vk::MemoryRequirement::HostVisible);
838 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
840 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
841 deMemcpy((ptr + m_offsetInBuffer), &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
843 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
845 if (m_testIndirectCountExt != IndirectCountType::NONE)
847 m_offsetInCountBuffer = sizeof(tcu::Vec3);
848 m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
849 m_context.getDevice(),
850 BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
851 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
852 m_context.getDefaultAllocator(),
853 vk::MemoryRequirement::HostVisible);
855 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
857 // For IndirectCountType::PARAM_LIMIT, the real limit will be set using the call parameter.
858 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
859 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount + (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? 0u : m_indirectCountExtDrawPadding);
861 *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
863 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
866 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
868 if (m_drawType == DRAW_TYPE_INDEXED)
870 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
873 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
877 case DRAW_TYPE_SEQUENTIAL:
879 if (m_testIndirectCountExt != IndirectCountType::NONE)
881 const deUint32 maxDrawCount = m_drawCount + (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_indirectCountExtDrawPadding : 0u);
882 m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
883 m_indirectCountBuffer->object(), m_offsetInCountBuffer,
884 maxDrawCount, m_strideInBuffer);
887 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
890 case DRAW_TYPE_INDEXED:
892 if (m_testIndirectCountExt != IndirectCountType::NONE)
894 const deUint32 maxDrawCount = m_drawCount + (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_indirectCountExtDrawPadding : 0u);
895 m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
896 m_indirectCountBuffer->object(), m_offsetInCountBuffer,
897 maxDrawCount, m_strideInBuffer);
900 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
904 TCU_FAIL("impossible");
909 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
913 case DRAW_TYPE_SEQUENTIAL:
915 if (m_testIndirectCountExt != IndirectCountType::NONE)
917 const deUint32 maxDrawCount = (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_drawCount + m_indirectCountExtDrawPadding : 1u);
918 m_vk.cmdDrawIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
919 m_indirectCountBuffer->object(), m_offsetInCountBuffer, maxDrawCount,
923 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
926 case DRAW_TYPE_INDEXED:
928 if (m_testIndirectCountExt != IndirectCountType::NONE)
930 const deUint32 maxDrawCount = (m_testIndirectCountExt == IndirectCountType::BUFFER_LIMIT ? m_drawCount + m_indirectCountExtDrawPadding : 1u);
931 m_vk.cmdDrawIndexedIndirectCount(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
932 m_indirectCountBuffer->object(), m_offsetInCountBuffer, maxDrawCount,
936 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
940 TCU_FAIL("impossible");
944 endRenderPass(m_vk, *m_cmdBuffer);
945 endCommandBuffer(m_vk, *m_cmdBuffer);
947 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
950 VK_CHECK(m_vk.queueWaitIdle(queue));
952 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5 + static_cast<float>(HEIGHT)));
954 referenceFrame.allocLevel(0);
956 const deInt32 frameWidth = referenceFrame.getWidth();
957 const deInt32 frameHeight = referenceFrame.getHeight();
959 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
961 ReferenceImageInstancedCoordinates refInstancedCoords;
963 for (int y = 0; y < frameHeight; y++)
965 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
967 for (int x = 0; x < frameWidth; x++)
969 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
971 if ((yCoord >= refInstancedCoords.bottom &&
972 yCoord <= refInstancedCoords.top &&
973 xCoord >= refInstancedCoords.left &&
974 xCoord <= refInstancedCoords.right))
975 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
979 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
980 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
981 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
983 qpTestResult res = QP_TEST_RESULT_PASS;
985 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
986 referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
988 res = QP_TEST_RESULT_FAIL;
991 return tcu::TestStatus(res, qpGetTestResultName(res));
994 void checkIndirectCountExt (Context& context)
996 context.requireDeviceFunctionality("VK_KHR_draw_indirect_count");
1001 IndirectDrawTests::IndirectDrawTests (tcu::TestContext& testCtx)
1002 : TestCaseGroup(testCtx, "indirect_draw", "indirect drawing simple geometry")
1004 /* Left blank on purpose */
1007 IndirectDrawTests::~IndirectDrawTests (void) {}
1010 void IndirectDrawTests::init (void)
1012 for (int drawTypeIdx = 0; drawTypeIdx < DRAWTYPE_LAST; drawTypeIdx++)
1014 std::string drawTypeStr;
1015 switch (drawTypeIdx)
1017 case DRAW_TYPE_SEQUENTIAL:
1018 drawTypeStr = "sequential";
1020 case DRAW_TYPE_INDEXED:
1021 drawTypeStr = "indexed";
1024 TCU_FAIL("impossible");
1027 tcu::TestCaseGroup* drawTypeGroup = new tcu::TestCaseGroup(m_testCtx, drawTypeStr.c_str(), ("Draws geometry using " + drawTypeStr + "draw call").c_str());
1029 tcu::TestCaseGroup* indirectDrawGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw", "Draws geometry");
1030 tcu::TestCaseGroup* indirectDrawCountGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count", "Draws geometry with VK_KHR_draw_indirect_count extension");
1031 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");
1033 IndirectDraw::TestSpec testSpec;
1034 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1035 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetch.vert";
1036 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1037 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1038 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
1039 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1040 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
1042 testSpec.testIndirectCountExt = IndirectCountType::BUFFER_LIMIT;
1043 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1044 indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_list", "Draws triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1045 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1046 indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1048 testSpec.testIndirectCountExt = IndirectCountType::PARAM_LIMIT;
1049 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1050 indirectDrawParamCountGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_list", "Draws triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1051 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1052 indirectDrawParamCountGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1054 drawTypeGroup->addChild(indirectDrawGroup);
1055 drawTypeGroup->addChild(indirectDrawCountGroup);
1056 drawTypeGroup->addChild(indirectDrawParamCountGroup);
1059 tcu::TestCaseGroup* indirectDrawFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_first_instance", "Draws geometry with different first instance in one commandbuffer");
1060 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");
1061 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");
1063 IndirectDraw::TestSpec testSpec;
1064 testSpec.testFirstInstanceNdx = true;
1065 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1066 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanceIndex.vert";
1067 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1068 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1069 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
1070 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1071 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
1073 testSpec.testIndirectCountExt = IndirectCountType::BUFFER_LIMIT;
1074 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1075 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_list", "Draws triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1076 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1077 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1079 testSpec.testIndirectCountExt = IndirectCountType::PARAM_LIMIT;
1080 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1081 indirectDrawParamCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_list", "Draws triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1082 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1083 indirectDrawParamCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1085 drawTypeGroup->addChild(indirectDrawFirstInstanceGroup);
1086 drawTypeGroup->addChild(indirectDrawCountFirstInstanceGroup);
1087 drawTypeGroup->addChild(indirectDrawParamCountFirstInstanceGroup);
1090 tcu::TestCaseGroup* indirectDrawInstancedGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_instanced", "Draws an instanced geometry");
1091 tcu::TestCaseGroup* indirectDrawCountInstancedGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count_instanced", "Draws an instanced geometry with VK_KHR_draw_indirect_count extension");
1092 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");
1094 tcu::TestCaseGroup* indirectDrawNoFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1095 tcu::TestCaseGroup* indirectDrawCountNoFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1096 tcu::TestCaseGroup* indirectDrawParamCountNoFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
1098 IndirectDrawInstanced<FirstInstanceNotSupported>::TestSpec testSpec;
1099 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1101 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanced.vert";
1102 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1104 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1105 indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1106 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1107 indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1109 testSpec.testIndirectCountExt = IndirectCountType::BUFFER_LIMIT;
1110 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1111 indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported>, FunctionSupport0>(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1112 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1113 indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported>, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1115 testSpec.testIndirectCountExt = IndirectCountType::PARAM_LIMIT;
1116 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1117 indirectDrawParamCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported>, FunctionSupport0>(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1118 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1119 indirectDrawParamCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported>, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1121 indirectDrawInstancedGroup->addChild(indirectDrawNoFirstInstanceGroup);
1122 indirectDrawCountInstancedGroup->addChild(indirectDrawCountNoFirstInstanceGroup);
1123 indirectDrawParamCountInstancedGroup->addChild(indirectDrawParamCountNoFirstInstanceGroup);
1125 tcu::TestCaseGroup* indirectDrawFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1126 tcu::TestCaseGroup* indirectDrawCountFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1127 tcu::TestCaseGroup* indirectDrawParamCountFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
1129 IndirectDrawInstanced<FirstInstanceSupported>::TestSpec testSpec;
1130 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
1132 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
1133 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
1135 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1136 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
1137 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1138 indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
1140 testSpec.testIndirectCountExt = IndirectCountType::BUFFER_LIMIT;
1141 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1142 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported>, FunctionSupport0>(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1143 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1144 indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported>, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1146 testSpec.testIndirectCountExt = IndirectCountType::PARAM_LIMIT;
1147 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1148 indirectDrawParamCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported>, FunctionSupport0>(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec, FunctionSupport0(checkIndirectCountExt)));
1149 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1150 indirectDrawParamCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported>, FunctionSupport0>(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec, FunctionSupport0(checkIndirectCountExt)));
1152 indirectDrawInstancedGroup->addChild(indirectDrawFirstInstanceGroup);
1153 indirectDrawCountInstancedGroup->addChild(indirectDrawCountFirstInstanceGroup);
1154 indirectDrawParamCountInstancedGroup->addChild(indirectDrawParamCountFirstInstanceGroup);
1156 drawTypeGroup->addChild(indirectDrawInstancedGroup);
1157 drawTypeGroup->addChild(indirectDrawCountInstancedGroup);
1158 drawTypeGroup->addChild(indirectDrawParamCountInstancedGroup);
1161 addChild(drawTypeGroup);