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"
71 struct DrawTypedTestSpec : public TestSpecBase
76 class IndirectDraw : public DrawTestsBaseClass
79 typedef DrawTypedTestSpec TestSpec;
81 IndirectDraw (Context &context, TestSpec testSpec);
82 virtual tcu::TestStatus iterate (void);
84 template<typename T> void addCommand (const T&);
87 std::vector<char> m_indirectBufferContents;
88 de::SharedPtr<Buffer> m_indirectBuffer;
89 vk::VkDeviceSize m_offsetInBuffer;
90 deUint32 m_strideInBuffer;
95 const DrawType m_drawType;
96 deBool m_isMultiDrawEnabled;
97 deUint32 m_drawIndirectMaxCount;
99 de::SharedPtr<Buffer> m_indexBuffer;
102 struct FirtsInstanceSupported
104 static deUint32 getFirstInstance (void) { return 2; }
105 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures& features) { return features.drawIndirectFirstInstance == VK_TRUE; }
108 struct FirtsInstanceNotSupported
110 static deUint32 getFirstInstance (void) { return 0; }
111 static bool isTestSupported (const vk::VkPhysicalDeviceFeatures&) { return true; }
114 template<class FirstInstanceSupport>
115 class IndirectDrawInstanced : public IndirectDraw
118 IndirectDrawInstanced (Context &context, TestSpec testSpec);
119 virtual tcu::TestStatus iterate (void);
122 IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
123 : DrawTestsBaseClass (context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
124 , m_drawType (testSpec.drawType)
127 int refVertexIndex = 2;
129 if (testSpec.drawType == DRAW_TYPE_INDEXED)
131 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
133 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
135 refVertexIndex += VERTEX_OFFSET;
138 m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
139 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
143 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
144 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
145 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
146 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
147 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
148 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
149 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
151 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
152 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
153 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
154 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
155 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
156 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
157 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
158 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
159 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
162 DE_FATAL("Unknown topology");
166 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
170 if (testSpec.drawType == DRAW_TYPE_INDEXED)
172 const size_t indexBufferLength = m_data.size() - VERTEX_OFFSET;
174 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);
175 deUint32* indices = reinterpret_cast<deUint32*>(m_indexBuffer->getBoundMemory().getHostPtr());
176 for (size_t i = 0; i < indexBufferLength; i++)
178 indices[i] = static_cast<deUint32>(i);
180 vk::flushMappedMemoryRange(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory().getMemory(), m_indexBuffer->getBoundMemory().getOffset(), sizeof(deUint32) * indexBufferLength);
183 // Check device for multidraw support:
184 if (m_context.getDeviceFeatures().multiDrawIndirect)
185 m_isMultiDrawEnabled = true;
187 m_isMultiDrawEnabled = false;
189 m_drawIndirectMaxCount = m_context.getDeviceProperties().limits.maxDrawIndirectCount;
194 void IndirectDraw::addCommand<vk::VkDrawIndirectCommand> (const vk::VkDrawIndirectCommand& command)
196 DE_ASSERT(m_drawType == DRAW_TYPE_SEQUENTIAL);
198 const size_t currentSize = m_indirectBufferContents.size();
200 m_indirectBufferContents.resize(currentSize + sizeof(command));
202 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
206 void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand>(const vk::VkDrawIndexedIndirectCommand& command)
208 DE_ASSERT(m_drawType == DRAW_TYPE_INDEXED);
210 const size_t currentSize = m_indirectBufferContents.size();
212 m_indirectBufferContents.resize(currentSize + sizeof(command));
214 deMemcpy(&m_indirectBufferContents[currentSize], &command, sizeof(command));
217 tcu::TestStatus IndirectDraw::iterate (void)
219 tcu::TestLog &log = m_context.getTestContext().getLog();
220 const vk::VkQueue queue = m_context.getUniversalQueue();
222 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
226 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
228 vk::VkDrawIndirectCommand drawCommands[] =
236 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
244 addCommand(drawCommands[0]);
245 addCommand(drawCommands[1]);
246 addCommand(drawCommands[2]);
249 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
251 vk::VkDrawIndirectCommand drawCommands[] =
259 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
267 addCommand(drawCommands[0]);
268 addCommand(drawCommands[1]);
269 addCommand(drawCommands[2]);
273 TCU_FAIL("impossible");
276 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
278 else if (m_drawType == DRAW_TYPE_INDEXED)
282 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
284 vk::VkDrawIndexedIndirectCommand drawCommands[] =
290 VERTEX_OFFSET, // vertexOffset
293 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
298 VERTEX_OFFSET, // vertexOffset
302 addCommand(drawCommands[0]);
303 addCommand(drawCommands[1]);
304 addCommand(drawCommands[2]);
307 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
309 vk::VkDrawIndexedIndirectCommand drawCommands[] =
315 VERTEX_OFFSET, // vertexOffset
318 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
323 VERTEX_OFFSET, // vertexOffset
327 addCommand(drawCommands[0]);
328 addCommand(drawCommands[1]);
329 addCommand(drawCommands[2]);
333 TCU_FAIL("impossible");
336 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
340 m_offsetInBuffer = sizeof(m_junkData);
344 const vk::VkDeviceSize vertexBufferOffset = 0;
345 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
347 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
349 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
351 m_indirectBuffer = Buffer::createAndAlloc( m_vk,
352 m_context.getDevice(),
353 BufferCreateInfo(dataSize + m_offsetInBuffer,
354 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
355 m_context.getDefaultAllocator(),
356 vk::MemoryRequirement::HostVisible);
358 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
360 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
361 deMemcpy(ptr + m_offsetInBuffer, &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
363 vk::flushMappedMemoryRange(m_vk,
364 m_context.getDevice(),
365 m_indirectBuffer->getBoundMemory().getMemory(),
366 m_indirectBuffer->getBoundMemory().getOffset(),
367 dataSize + m_offsetInBuffer);
369 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
371 if (m_drawType == DRAW_TYPE_INDEXED)
373 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
376 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
380 case DRAW_TYPE_SEQUENTIAL:
381 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
383 case DRAW_TYPE_INDEXED:
384 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
387 TCU_FAIL("impossible");
392 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
396 case DRAW_TYPE_SEQUENTIAL:
397 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
399 case DRAW_TYPE_INDEXED:
400 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
403 TCU_FAIL("impossible");
407 m_vk.cmdEndRenderPass(*m_cmdBuffer);
408 m_vk.endCommandBuffer(*m_cmdBuffer);
410 vk::VkSubmitInfo submitInfo =
412 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
413 DE_NULL, // const void* pNext;
414 0, // deUint32 waitSemaphoreCount;
415 DE_NULL, // const VkSemaphore* pWaitSemaphores;
416 (const vk::VkPipelineStageFlags*)DE_NULL,
417 1, // deUint32 commandBufferCount;
418 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
419 0, // deUint32 signalSemaphoreCount;
420 DE_NULL // const VkSemaphore* pSignalSemaphores;
422 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
424 VK_CHECK(m_vk.queueWaitIdle(queue));
427 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
428 referenceFrame.allocLevel(0);
430 const deInt32 frameWidth = referenceFrame.getWidth();
431 const deInt32 frameHeight = referenceFrame.getHeight();
433 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
435 ReferenceImageCoordinates refCoords;
437 for (int y = 0; y < frameHeight; y++)
439 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
441 for (int x = 0; x < frameWidth; x++)
443 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
445 if ((yCoord >= refCoords.bottom &&
446 yCoord <= refCoords.top &&
447 xCoord >= refCoords.left &&
448 xCoord <= refCoords.right))
449 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
453 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
454 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
455 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
457 qpTestResult res = QP_TEST_RESULT_PASS;
459 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
460 referenceFrame.getLevel(0), renderedFrame, 0.05f,
461 tcu::COMPARE_LOG_RESULT)) {
462 res = QP_TEST_RESULT_FAIL;
465 return tcu::TestStatus(res, qpGetTestResultName(res));
469 template<class FirstInstanceSupport>
470 IndirectDrawInstanced<FirstInstanceSupport>::IndirectDrawInstanced (Context &context, TestSpec testSpec)
471 : IndirectDraw(context, testSpec)
473 if (!FirstInstanceSupport::isTestSupported(m_context.getDeviceFeatures()))
475 throw tcu::NotSupportedError("Required 'drawIndirectFirstInstance' feature is not supported");
479 template<class FirstInstanceSupport>
480 tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
482 tcu::TestLog &log = m_context.getTestContext().getLog();
483 const vk::VkQueue queue = m_context.getUniversalQueue();
485 if (m_drawType == DRAW_TYPE_SEQUENTIAL)
489 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
491 vk::VkDrawIndirectCommand drawCmd[] =
497 FirstInstanceSupport::getFirstInstance() //firstInstance
499 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
504 FirstInstanceSupport::getFirstInstance() //firstInstance
507 addCommand(drawCmd[0]);
508 addCommand(drawCmd[1]);
509 addCommand(drawCmd[2]);
512 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
514 vk::VkDrawIndirectCommand drawCmd[] =
520 FirstInstanceSupport::getFirstInstance() //firstInstance
522 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 },
527 FirstInstanceSupport::getFirstInstance() //firstInstance
530 addCommand(drawCmd[0]);
531 addCommand(drawCmd[1]);
532 addCommand(drawCmd[2]);
536 TCU_FAIL("impossible");
540 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndirectCommand);
542 else if (m_drawType == DRAW_TYPE_INDEXED)
546 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
548 vk::VkDrawIndexedIndirectCommand drawCmd[] =
554 VERTEX_OFFSET, // vertexOffset
555 FirstInstanceSupport::getFirstInstance() // firstInstance
557 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
562 VERTEX_OFFSET, // vertexOffset
563 FirstInstanceSupport::getFirstInstance() // firstInstance
566 addCommand(drawCmd[0]);
567 addCommand(drawCmd[1]);
568 addCommand(drawCmd[2]);
571 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
573 vk::VkDrawIndexedIndirectCommand drawCmd[] =
579 VERTEX_OFFSET, // vertexOffset
580 FirstInstanceSupport::getFirstInstance() // firstInstance
582 { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
587 VERTEX_OFFSET, // vertexOffset
588 FirstInstanceSupport::getFirstInstance() // firstInstance
591 addCommand(drawCmd[0]);
592 addCommand(drawCmd[1]);
593 addCommand(drawCmd[2]);
597 TCU_FAIL("impossible");
601 m_strideInBuffer = 2 * (deUint32)sizeof(vk::VkDrawIndexedIndirectCommand);
605 m_offsetInBuffer = sizeof(m_junkData);
609 const vk::VkDeviceSize vertexBufferOffset = 0;
610 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
612 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
614 const vk::VkDeviceSize dataSize = m_indirectBufferContents.size();
616 m_indirectBuffer = Buffer::createAndAlloc( m_vk,
617 m_context.getDevice(),
618 BufferCreateInfo(dataSize + m_offsetInBuffer,
619 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
620 m_context.getDefaultAllocator(),
621 vk::MemoryRequirement::HostVisible);
623 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
625 deMemcpy(ptr, &m_junkData, static_cast<size_t>(m_offsetInBuffer));
626 deMemcpy((ptr + m_offsetInBuffer), &m_indirectBufferContents[0], static_cast<size_t>(dataSize));
628 vk::flushMappedMemoryRange(m_vk,
629 m_context.getDevice(),
630 m_indirectBuffer->getBoundMemory().getMemory(),
631 m_indirectBuffer->getBoundMemory().getOffset(),
632 dataSize + m_offsetInBuffer);
634 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
636 if (m_drawType == DRAW_TYPE_INDEXED)
638 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, m_indexBuffer->object(), DE_NULL, vk::VK_INDEX_TYPE_UINT32);
641 if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
645 case DRAW_TYPE_SEQUENTIAL:
646 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
648 case DRAW_TYPE_INDEXED:
649 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
652 TCU_FAIL("impossible");
657 for (deUint32 drawNdx = 0; drawNdx < m_drawCount; drawNdx++)
661 case DRAW_TYPE_SEQUENTIAL:
662 m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
664 case DRAW_TYPE_INDEXED:
665 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
668 TCU_FAIL("impossible");
672 m_vk.cmdEndRenderPass(*m_cmdBuffer);
673 m_vk.endCommandBuffer(*m_cmdBuffer);
675 vk::VkSubmitInfo submitInfo =
677 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
678 DE_NULL, // const void* pNext;
679 0, // deUint32 waitSemaphoreCount;
680 DE_NULL, // const VkSemaphore* pWaitSemaphores;
681 (const vk::VkPipelineStageFlags*)DE_NULL,
682 1, // deUint32 commandBufferCount;
683 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
684 0, // deUint32 signalSemaphoreCount;
685 DE_NULL // const VkSemaphore* pSignalSemaphores;
687 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
689 VK_CHECK(m_vk.queueWaitIdle(queue));
692 VK_CHECK(m_vk.queueWaitIdle(queue));
694 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
696 referenceFrame.allocLevel(0);
698 const deInt32 frameWidth = referenceFrame.getWidth();
699 const deInt32 frameHeight = referenceFrame.getHeight();
701 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
703 ReferenceImageInstancedCoordinates refInstancedCoords;
705 for (int y = 0; y < frameHeight; y++)
707 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
709 for (int x = 0; x < frameWidth; x++)
711 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
713 if ((yCoord >= refInstancedCoords.bottom &&
714 yCoord <= refInstancedCoords.top &&
715 xCoord >= refInstancedCoords.left &&
716 xCoord <= refInstancedCoords.right))
717 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
721 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
722 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
723 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
725 qpTestResult res = QP_TEST_RESULT_PASS;
727 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
728 referenceFrame.getLevel(0), renderedFrame, 0.05f,
729 tcu::COMPARE_LOG_RESULT)) {
730 res = QP_TEST_RESULT_FAIL;
733 return tcu::TestStatus(res, qpGetTestResultName(res));
739 IndirectDrawTests::IndirectDrawTests (tcu::TestContext& testCtx)
740 : TestCaseGroup(testCtx, "indirect_draw", "indirect drawing simple geometry")
742 /* Left blank on purpose */
745 IndirectDrawTests::~IndirectDrawTests (void) {}
748 void IndirectDrawTests::init (void)
750 for (int drawTypeIdx = 0; drawTypeIdx < DRAWTYPE_LAST; drawTypeIdx++)
752 std::string drawTypeStr;
755 case DRAW_TYPE_SEQUENTIAL:
756 drawTypeStr = "sequential";
758 case DRAW_TYPE_INDEXED:
759 drawTypeStr = "indexed";
762 TCU_FAIL("impossible");
765 tcu::TestCaseGroup* drawTypeGroup = new tcu::TestCaseGroup(m_testCtx, drawTypeStr.c_str(), ("Draws geometry using " + drawTypeStr + "draw call").c_str());
767 tcu::TestCaseGroup* indirectDrawGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw", "Draws geometry");
769 IndirectDraw::TestSpec testSpec;
770 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
771 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetch.vert";
772 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
773 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
774 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
775 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
776 indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
778 drawTypeGroup->addChild(indirectDrawGroup);
781 tcu::TestCaseGroup* indirectDrawInstancedGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_instanced", "Draws an instanced geometry");
783 tcu::TestCaseGroup* noFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
785 IndirectDrawInstanced<FirtsInstanceNotSupported>::TestSpec testSpec;
786 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
788 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanced.vert";
789 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
791 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
792 noFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
793 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
794 noFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
796 indirectDrawInstancedGroup->addChild(noFirstInstanceGroup);
798 tcu::TestCaseGroup* firstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
800 IndirectDrawInstanced<FirtsInstanceSupported>::TestSpec testSpec;
801 testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
803 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
804 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
806 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
807 firstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
808 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
809 firstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
811 indirectDrawInstancedGroup->addChild(firstInstanceGroup);
813 drawTypeGroup->addChild(indirectDrawInstancedGroup);
816 addChild(drawTypeGroup);