1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Danylo Piliaiev <danylo.piliaiev@gmail.com>
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 Test for conditional rendering of vkCmdDraw* functions
23 *//*--------------------------------------------------------------------*/
25 #include "vktConditionalDrawTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawTestCaseUtil.hpp"
31 #include "vktDrawBaseClass.hpp"
33 #include "vkTypeUtil.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuResource.hpp"
37 #include "tcuImageCompare.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuRGBA.hpp"
42 #include "vkCmdUtil.hpp"
53 DRAW_COMMAND_TYPE_DRAW = 0,
54 DRAW_COMMAND_TYPE_DRAW_INDEXED,
55 DRAW_COMMAND_TYPE_DRAW_INDIRECT,
56 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
57 DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT,
58 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT,
60 DRAW_COMMAND_TYPE_DRAW_LAST
63 const char* getDrawCommandTypeName (DrawCommandType command)
67 case DRAW_COMMAND_TYPE_DRAW: return "draw";
68 case DRAW_COMMAND_TYPE_DRAW_INDEXED: return "draw_indexed";
69 case DRAW_COMMAND_TYPE_DRAW_INDIRECT: return "draw_indirect";
70 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT: return "draw_indexed_indirect";
71 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT: return "draw_indirect_count";
72 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT: return "draw_indexed_indirect_count";
73 default: DE_ASSERT(false);
78 struct ConditionalTestSpec : public Draw::TestSpecBase
80 DrawCommandType command;
82 ConditionalData conditionalData;
85 class ConditionalDraw : public Draw::DrawTestsBaseClass
88 typedef ConditionalTestSpec TestSpec;
90 ConditionalDraw (Context &context, ConditionalTestSpec testSpec);
92 virtual tcu::TestStatus iterate (void);
93 void createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer);
94 void createIndirectBuffer (void);
95 void createIndexedIndirectBuffer (void);
96 void createIndirectCountBuffer (void);
97 void recordDraw (vk::VkCommandBuffer cmdBuffer);
100 void createRenderPassWithClear (void);
102 const DrawCommandType m_command;
103 const deUint32 m_drawCalls;
105 const ConditionalData m_conditionalData;
106 de::SharedPtr<Draw::Buffer> m_conditionalBuffer;
108 vk::Move<vk::VkCommandBuffer> m_secondaryCmdBuffer;
110 std::vector<deUint32> m_indexes;
111 de::SharedPtr<Draw::Buffer> m_indexBuffer;
113 de::SharedPtr<Draw::Buffer> m_indirectBuffer;
114 de::SharedPtr<Draw::Buffer> m_indirectCountBuffer;
116 // For cases where we want to clear the attachment in the render pass begin operation.
117 vk::Move<vk::VkRenderPass> m_rpWithClear;
118 vk::Move<vk::VkFramebuffer> m_fbWithClear;
121 void checkSupport(Context& context, DrawCommandType command)
123 if (command == DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT || command == DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT)
124 context.requireDeviceFunctionality("VK_KHR_draw_indirect_count");
127 ConditionalDraw::ConditionalDraw (Context &context, ConditionalTestSpec testSpec)
128 : Draw::DrawTestsBaseClass(context,
129 testSpec.shaders[glu::SHADERTYPE_VERTEX],
130 testSpec.shaders[glu::SHADERTYPE_FRAGMENT],
131 Draw::SharedGroupParams(new Draw::GroupParams{ false, false, false }),
132 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
133 , m_command(testSpec.command)
134 , m_drawCalls(testSpec.drawCalls)
135 , m_conditionalData(testSpec.conditionalData)
137 checkConditionalRenderingCapabilities(context, m_conditionalData);
138 checkSupport(context, m_command);
140 const float minX = -0.3f;
141 const float maxX = 0.3f;
142 const float drawStep = 0.6f / static_cast<float>(m_drawCalls);
144 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
146 const float minY = minX + static_cast<float>(drawIdx) * drawStep;
147 const float maxY = minY + drawStep;
149 m_data.push_back(Draw::VertexElementData(tcu::Vec4( minX, maxY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
150 m_data.push_back(Draw::VertexElementData(tcu::Vec4( minX, minY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
151 m_data.push_back(Draw::VertexElementData(tcu::Vec4( maxX, maxY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
153 m_data.push_back(Draw::VertexElementData(tcu::Vec4( minX, minY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
154 m_data.push_back(Draw::VertexElementData(tcu::Vec4( maxX, maxY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
155 m_data.push_back(Draw::VertexElementData(tcu::Vec4( maxX, minY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
158 m_data.push_back(Draw::VertexElementData(tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
159 m_data.push_back(Draw::VertexElementData(tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
160 m_data.push_back(Draw::VertexElementData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
162 m_data.push_back(Draw::VertexElementData(tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
163 m_data.push_back(Draw::VertexElementData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
164 m_data.push_back(Draw::VertexElementData(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
166 for (deUint32 index = 0; index < m_data.size(); index++)
168 m_indexes.push_back(index);
173 DE_ASSERT(!(m_conditionalData.clearInRenderPass && m_conditionalData.conditionInSecondaryCommandBuffer));
175 if (m_conditionalData.clearInRenderPass)
176 createRenderPassWithClear();
178 m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
181 void ConditionalDraw::createRenderPassWithClear (void)
183 const auto device = m_context.getDevice();
184 Draw::RenderPassCreateInfo renderPassCreateInfo;
186 renderPassCreateInfo.addAttachment(Draw::AttachmentDescription(m_colorAttachmentFormat,
187 vk::VK_SAMPLE_COUNT_1_BIT,
188 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // Clear with the render pass.
189 vk::VK_ATTACHMENT_STORE_OP_STORE,
190 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
191 vk::VK_ATTACHMENT_STORE_OP_STORE,
192 vk::VK_IMAGE_LAYOUT_UNDEFINED,
193 vk::VK_IMAGE_LAYOUT_GENERAL));
195 const vk::VkAttachmentReference colorAttachmentReference
198 vk::VK_IMAGE_LAYOUT_GENERAL
201 renderPassCreateInfo.addSubpass(Draw::SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
206 &colorAttachmentReference,
208 Draw::AttachmentReference(),
212 m_rpWithClear = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
215 std::vector<vk::VkImageView> colorAttachments { *m_colorTargetView };
216 const Draw::FramebufferCreateInfo framebufferCreateInfo (*m_rpWithClear, colorAttachments, WIDTH, HEIGHT, 1);
218 m_fbWithClear = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
221 void ConditionalDraw::createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer)
223 const vk::VkDeviceSize indexDataSize = m_indexes.size() * sizeof(deUint32);
224 m_indexBuffer = Draw::Buffer::createAndAlloc(m_vk, m_context.getDevice(),
225 Draw::BufferCreateInfo(indexDataSize,
226 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
227 m_context.getDefaultAllocator(),
228 vk::MemoryRequirement::HostVisible);
230 deUint8* indexBufferPtr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
231 deMemcpy(indexBufferPtr, &m_indexes[0], static_cast<size_t>(indexDataSize));
233 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
235 const vk::VkBuffer indexBuffer = m_indexBuffer->object();
236 m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
239 void ConditionalDraw::createIndirectBuffer (void)
241 const vk::VkDrawIndirectCommand badDrawCommand =
245 m_drawCalls * 6u, // firstVertex
249 std::vector<vk::VkDrawIndirectCommand> drawCommands;
250 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
252 const vk::VkDrawIndirectCommand goodDrawCommand =
256 6u * drawIdx, // firstVertex
260 drawCommands.push_back(goodDrawCommand);
261 // *Bad* commands should not be rendered by vkCmdDrawIndirectCountKHR
262 drawCommands.push_back(badDrawCommand);
263 drawCommands.push_back(badDrawCommand);
266 const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndirectCommand);
268 m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
269 m_context.getDevice(),
270 Draw::BufferCreateInfo(drawCommandsSize,
271 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
272 m_context.getDefaultAllocator(),
273 vk::MemoryRequirement::HostVisible);
275 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
276 deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
278 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
281 void ConditionalDraw::createIndexedIndirectBuffer (void)
283 const vk::VkDrawIndexedIndirectCommand badDrawCommand =
287 m_drawCalls * 6u, // firstIndex
292 std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
293 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
295 const vk::VkDrawIndexedIndirectCommand goodDrawCommand =
299 6u * drawIdx, // firstIndex
304 drawCommands.push_back(goodDrawCommand);
305 // *Bad* commands should not be rendered by vkCmdDrawIndexedIndirectCountKHR
306 drawCommands.push_back(badDrawCommand);
307 drawCommands.push_back(badDrawCommand);
310 const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
312 m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
313 m_context.getDevice(),
314 Draw::BufferCreateInfo(drawCommandsSize,
315 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
316 m_context.getDefaultAllocator(),
317 vk::MemoryRequirement::HostVisible);
319 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
320 deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
322 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
325 void ConditionalDraw::createIndirectCountBuffer (void)
327 m_indirectCountBuffer = Draw::Buffer::createAndAlloc(m_vk,
328 m_context.getDevice(),
329 Draw::BufferCreateInfo(sizeof(deUint32),
330 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
331 m_context.getDefaultAllocator(),
332 vk::MemoryRequirement::HostVisible);
334 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
335 *(deUint32*)(countBufferPtr) = 1;
337 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
340 void ConditionalDraw::recordDraw(vk::VkCommandBuffer cmdBuffer)
342 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
344 /* Indirect buffer has next layout:
345 * goodCommand badCommand badCommand goodCommand badCommand badCommand ...
347 const vk::VkDeviceSize indirectOffset = sizeof(vk::VkDrawIndirectCommand) * drawIdx * 3;
348 const vk::VkDeviceSize indexedIndirectOffset = sizeof(vk::VkDrawIndexedIndirectCommand) * drawIdx * 3;
351 case DRAW_COMMAND_TYPE_DRAW:
353 m_vk.cmdDraw(cmdBuffer, 6, 1, 6 * drawIdx, 0);
356 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
358 m_vk.cmdDrawIndexed(cmdBuffer, 6, 1, 6 * drawIdx, 0, 0);
361 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
363 m_vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer->object(), indirectOffset, 1, 0);
366 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
368 m_vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer->object(), indexedIndirectOffset, 1, 0);
371 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
373 m_vk.cmdDrawIndirectCount( cmdBuffer,
374 m_indirectBuffer->object(), indirectOffset,
375 m_indirectCountBuffer->object(), 0, 3,
376 sizeof(vk::VkDrawIndirectCommand));
379 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
381 m_vk.cmdDrawIndexedIndirectCount(cmdBuffer,
382 m_indirectBuffer->object(), indexedIndirectOffset,
383 m_indirectCountBuffer->object(), 0, 3,
384 sizeof(vk::VkDrawIndexedIndirectCommand));
387 default: DE_ASSERT(false);
392 tcu::TestStatus ConditionalDraw::iterate (void)
394 tcu::TestLog& log = m_context.getTestContext().getLog();
395 const vk::VkQueue queue = m_context.getUniversalQueue();
396 const vk::VkDevice device = m_context.getDevice();
398 // We will clear to a different color to be sure.
399 const auto clearColor = (m_conditionalData.clearInRenderPass ? tcu::RGBA::white().toVec() : tcu::RGBA::black().toVec());
401 m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
403 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
406 const bool useSecondaryCmdBuffer = m_conditionalData.conditionInherited || m_conditionalData.conditionInSecondaryCommandBuffer;
407 const auto subpassContents = (useSecondaryCmdBuffer ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE);
409 if (m_conditionalData.clearInRenderPass)
411 // When clearing in the render pass we want to check the render pass clear is executed properly.
412 beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
413 vk::beginRenderPass(m_vk, *m_cmdBuffer, *m_rpWithClear, *m_fbWithClear, vk::makeRect2D(WIDTH, HEIGHT), clearColor, subpassContents);
417 beginLegacyRender(*m_cmdBuffer, subpassContents);
420 vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;
422 if (useSecondaryCmdBuffer)
424 const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
426 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
428 m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE // conditionalRenderingEnable
431 const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
433 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
434 &conditionalRenderingInheritanceInfo,
435 *m_renderPass, // renderPass
437 *m_framebuffer, // framebuffer
438 VK_FALSE, // occlusionQueryEnable
439 (vk::VkQueryControlFlags)0u, // queryFlags
440 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
443 const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
445 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
447 vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
451 VK_CHECK(m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo));
453 targetCmdBuffer = *m_secondaryCmdBuffer;
456 const vk::VkDeviceSize vertexBufferOffset = 0;
457 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
459 m_vk.cmdBindVertexBuffers(targetCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
463 case DRAW_COMMAND_TYPE_DRAW:
467 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
469 createAndBindIndexBuffer(targetCmdBuffer);
472 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
474 createIndirectBuffer();
477 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
479 createAndBindIndexBuffer(targetCmdBuffer);
480 createIndexedIndirectBuffer();
483 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
485 createIndirectBuffer();
486 createIndirectCountBuffer();
489 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
491 createAndBindIndexBuffer(targetCmdBuffer);
492 createIndexedIndirectBuffer();
493 createIndirectCountBuffer();
496 default: DE_ASSERT(false);
499 m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
501 if (m_conditionalData.conditionInSecondaryCommandBuffer)
503 beginConditionalRendering(m_vk, *m_secondaryCmdBuffer, *m_conditionalBuffer, m_conditionalData);
504 recordDraw(*m_secondaryCmdBuffer);
505 m_vk.cmdEndConditionalRenderingEXT(*m_secondaryCmdBuffer);
506 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
508 else if (m_conditionalData.conditionInherited)
510 recordDraw(*m_secondaryCmdBuffer);
511 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
514 if (m_conditionalData.conditionInPrimaryCommandBuffer)
516 if (!m_conditionalData.clearInRenderPass)
517 beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
519 if (m_conditionalData.conditionInherited)
521 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
525 recordDraw(*m_cmdBuffer);
528 if (!m_conditionalData.clearInRenderPass)
529 m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
531 else if (useSecondaryCmdBuffer)
533 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
536 if (m_conditionalData.clearInRenderPass)
538 // Finish conditional rendering outside the render pass.
539 vk::endRenderPass(m_vk, *m_cmdBuffer);
540 m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
544 endLegacyRender(*m_cmdBuffer);
547 endCommandBuffer(m_vk, *m_cmdBuffer);
549 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
552 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
553 referenceFrame.allocLevel(0);
555 const deInt32 frameWidth = referenceFrame.getWidth();
556 const deInt32 frameHeight = referenceFrame.getHeight();
558 tcu::clear(referenceFrame.getLevel(0), clearColor);
560 const tcu::Vec4 drawColor = tcu::RGBA::blue().toVec();
561 const tcu::Vec4 referenceColor = m_conditionalData.expectCommandExecution ? drawColor : clearColor;
563 Draw::ReferenceImageCoordinates refCoords;
565 for (int y = 0; y < frameHeight; y++)
567 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
569 for (int x = 0; x < frameWidth; x++)
571 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
573 if ((yCoord >= refCoords.bottom &&
574 yCoord <= refCoords.top &&
575 xCoord >= refCoords.left &&
576 xCoord <= refCoords.right))
577 referenceFrame.getLevel(0).setPixel(referenceColor, x, y);
581 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
582 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
583 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
585 qpTestResult res = QP_TEST_RESULT_PASS;
587 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
588 referenceFrame.getLevel(0), renderedFrame, 0.05f,
589 tcu::COMPARE_LOG_RESULT))
591 res = QP_TEST_RESULT_FAIL;
594 return tcu::TestStatus(res, qpGetTestResultName(res));
599 ConditionalDrawTests::ConditionalDrawTests (tcu::TestContext &testCtx)
600 : TestCaseGroup (testCtx, "draw", "Conditional Rendering Of Draw Commands")
602 /* Left blank on purpose */
605 ConditionalDrawTests::~ConditionalDrawTests (void) {}
607 void ConditionalDrawTests::init (void)
609 for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
611 const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
613 tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "Conditionaly execute draw calls");
615 for (deUint32 commandTypeIdx = 0; commandTypeIdx < DRAW_COMMAND_TYPE_DRAW_LAST; ++commandTypeIdx)
617 const DrawCommandType command = DrawCommandType(commandTypeIdx);
619 ConditionalTestSpec testSpec;
620 testSpec.command = command;
621 testSpec.drawCalls = 4;
622 testSpec.conditionalData = conditionData;
623 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
624 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
626 conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalDraw>(m_testCtx, getDrawCommandTypeName(command), "", testSpec));
629 addChild(conditionalDrawRootGroup);