1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Danylo Piliaiev <danylo.piliaiev@gmail.com>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Test for conditional rendering of vkCmdDraw* functions
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktConditionalDrawTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
27
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawTestCaseUtil.hpp"
30
31 #include "vktDrawBaseClass.hpp"
32
33 #include "tcuTestLog.hpp"
34 #include "tcuResource.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuRGBA.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkCmdUtil.hpp"
41
42 namespace vkt
43 {
44 namespace conditional
45 {
46 namespace
47 {
48
49 enum DrawCommandType
50 {
51 DRAW_COMMAND_TYPE_DRAW = 0,
52 DRAW_COMMAND_TYPE_DRAW_INDEXED,
53 DRAW_COMMAND_TYPE_DRAW_INDIRECT,
54 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
55 DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT,
56 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT,
57
58 DRAW_COMMAND_TYPE_DRAW_LAST
59 };
60
getDrawCommandTypeName(DrawCommandType command)61 const char* getDrawCommandTypeName (DrawCommandType command)
62 {
63 switch (command)
64 {
65 case DRAW_COMMAND_TYPE_DRAW: return "draw";
66 case DRAW_COMMAND_TYPE_DRAW_INDEXED: return "draw_indexed";
67 case DRAW_COMMAND_TYPE_DRAW_INDIRECT: return "draw_indirect";
68 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT: return "draw_indexed_indirect";
69 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT: return "draw_indirect_count";
70 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT: return "draw_indexed_indirect_count";
71 default: DE_ASSERT(false);
72 }
73 return "";
74 }
75
76 struct ConditionalTestSpec : public Draw::TestSpecBase
77 {
78 DrawCommandType command;
79 deUint32 drawCalls;
80 ConditionalData conditionalData;
81 };
82
83 class ConditionalDraw : public Draw::DrawTestsBaseClass
84 {
85 public:
86 typedef ConditionalTestSpec TestSpec;
87
88 ConditionalDraw (Context &context, ConditionalTestSpec testSpec);
89
90 virtual tcu::TestStatus iterate (void);
91 void createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer);
92 void createIndirectBuffer (void);
93 void createIndexedIndirectBuffer (void);
94 void createIndirectCountBuffer (void);
95 void recordDraw (vk::VkCommandBuffer cmdBuffer);
96
97 protected:
98 const DrawCommandType m_command;
99 const deUint32 m_drawCalls;
100
101 const ConditionalData m_conditionalData;
102 de::SharedPtr<Draw::Buffer> m_conditionalBuffer;
103
104 vk::Move<vk::VkCommandBuffer> m_secondaryCmdBuffer;
105
106 std::vector<deUint32> m_indexes;
107 de::SharedPtr<Draw::Buffer> m_indexBuffer;
108
109 de::SharedPtr<Draw::Buffer> m_indirectBuffer;
110 de::SharedPtr<Draw::Buffer> m_indirectCountBuffer;
111 };
112
ConditionalDraw(Context & context,ConditionalTestSpec testSpec)113 ConditionalDraw::ConditionalDraw (Context &context, ConditionalTestSpec testSpec)
114 : Draw::DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], false, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
115 , m_command(testSpec.command)
116 , m_drawCalls(testSpec.drawCalls)
117 , m_conditionalData(testSpec.conditionalData)
118 {
119 checkConditionalRenderingCapabilities(context, m_conditionalData);
120
121 const float minX = -0.3f;
122 const float maxX = 0.3f;
123 const float drawStep = 0.6f / static_cast<float>(m_drawCalls);
124
125 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
126 {
127 const float minY = minX + static_cast<float>(drawIdx) * drawStep;
128 const float maxY = minY + drawStep;
129
130 m_data.push_back(Draw::VertexElementData(tcu::Vec4( minX, maxY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
131 m_data.push_back(Draw::VertexElementData(tcu::Vec4( minX, minY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
132 m_data.push_back(Draw::VertexElementData(tcu::Vec4( maxX, maxY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
133
134 m_data.push_back(Draw::VertexElementData(tcu::Vec4( minX, minY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
135 m_data.push_back(Draw::VertexElementData(tcu::Vec4( maxX, maxY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
136 m_data.push_back(Draw::VertexElementData(tcu::Vec4( maxX, minY, 0.5f, 1.0f), tcu::RGBA::blue().toVec(), 0));
137 }
138
139 m_data.push_back(Draw::VertexElementData(tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
140 m_data.push_back(Draw::VertexElementData(tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
141 m_data.push_back(Draw::VertexElementData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
142
143 m_data.push_back(Draw::VertexElementData(tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
144 m_data.push_back(Draw::VertexElementData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
145 m_data.push_back(Draw::VertexElementData(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::red().toVec(), 0));
146
147 for (deUint32 index = 0; index < m_data.size(); index++)
148 {
149 m_indexes.push_back(index);
150 }
151
152 initialize();
153
154 m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
155 }
156
createAndBindIndexBuffer(vk::VkCommandBuffer cmdBuffer)157 void ConditionalDraw::createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer)
158 {
159 const vk::VkDeviceSize indexDataSize = m_indexes.size() * sizeof(deUint32);
160 m_indexBuffer = Draw::Buffer::createAndAlloc(m_vk, m_context.getDevice(),
161 Draw::BufferCreateInfo(indexDataSize,
162 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
163 m_context.getDefaultAllocator(),
164 vk::MemoryRequirement::HostVisible);
165
166 deUint8* indexBufferPtr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
167 deMemcpy(indexBufferPtr, &m_indexes[0], static_cast<size_t>(indexDataSize));
168
169 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
170
171 const vk::VkBuffer indexBuffer = m_indexBuffer->object();
172 m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
173 }
174
createIndirectBuffer(void)175 void ConditionalDraw::createIndirectBuffer (void)
176 {
177 const vk::VkDrawIndirectCommand badDrawCommand =
178 {
179 6u, // vertexCount
180 1u, // instanceCount
181 m_drawCalls * 6u, // firstVertex
182 0u // firstInstance
183 };
184
185 std::vector<vk::VkDrawIndirectCommand> drawCommands;
186 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
187 {
188 const vk::VkDrawIndirectCommand goodDrawCommand =
189 {
190 6u, // vertexCount
191 1u, // instanceCount
192 6u * drawIdx, // firstVertex
193 0u // firstInstance
194 };
195
196 drawCommands.push_back(goodDrawCommand);
197 // *Bad* commands should not be rendered by vkCmdDrawIndirectCountKHR
198 drawCommands.push_back(badDrawCommand);
199 drawCommands.push_back(badDrawCommand);
200 }
201
202 const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndirectCommand);
203
204 m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
205 m_context.getDevice(),
206 Draw::BufferCreateInfo(drawCommandsSize,
207 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
208 m_context.getDefaultAllocator(),
209 vk::MemoryRequirement::HostVisible);
210
211 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
212 deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
213
214 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
215 }
216
createIndexedIndirectBuffer(void)217 void ConditionalDraw::createIndexedIndirectBuffer (void)
218 {
219 const vk::VkDrawIndexedIndirectCommand badDrawCommand =
220 {
221 6u, // indexCount
222 1u, // instanceCount
223 m_drawCalls * 6u, // firstIndex
224 0u, // vertexOffset
225 0u, // firstInstance
226 };
227
228 std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
229 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
230 {
231 const vk::VkDrawIndexedIndirectCommand goodDrawCommand =
232 {
233 6u, // indexCount
234 1u, // instanceCount
235 6u * drawIdx, // firstIndex
236 0u, // vertexOffset
237 0u, // firstInstance
238 };
239
240 drawCommands.push_back(goodDrawCommand);
241 // *Bad* commands should not be rendered by vkCmdDrawIndexedIndirectCountKHR
242 drawCommands.push_back(badDrawCommand);
243 drawCommands.push_back(badDrawCommand);
244 }
245
246 const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
247
248 m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
249 m_context.getDevice(),
250 Draw::BufferCreateInfo(drawCommandsSize,
251 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
252 m_context.getDefaultAllocator(),
253 vk::MemoryRequirement::HostVisible);
254
255 deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
256 deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
257
258 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
259 }
260
createIndirectCountBuffer(void)261 void ConditionalDraw::createIndirectCountBuffer (void)
262 {
263 m_indirectCountBuffer = Draw::Buffer::createAndAlloc(m_vk,
264 m_context.getDevice(),
265 Draw::BufferCreateInfo(sizeof(deUint32),
266 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
267 m_context.getDefaultAllocator(),
268 vk::MemoryRequirement::HostVisible);
269
270 deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
271 *(deUint32*)(countBufferPtr) = 1;
272
273 vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
274 }
275
recordDraw(vk::VkCommandBuffer cmdBuffer)276 void ConditionalDraw::recordDraw(vk::VkCommandBuffer cmdBuffer)
277 {
278 for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
279 {
280 /* Indirect buffer has next layout:
281 * goodCommand badCommand badCommand goodCommand badCommand badCommand ...
282 */
283 const vk::VkDeviceSize indirectOffset = sizeof(vk::VkDrawIndirectCommand) * drawIdx * 3;
284 const vk::VkDeviceSize indexedIndirectOffset = sizeof(vk::VkDrawIndexedIndirectCommand) * drawIdx * 3;
285 switch (m_command)
286 {
287 case DRAW_COMMAND_TYPE_DRAW:
288 {
289 m_vk.cmdDraw(cmdBuffer, 6, 1, 6 * drawIdx, 0);
290 break;
291 }
292 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
293 {
294 m_vk.cmdDrawIndexed(cmdBuffer, 6, 1, 6 * drawIdx, 0, 0);
295 break;
296 }
297 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
298 {
299 m_vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer->object(), indirectOffset, 1, 0);
300 break;
301 }
302 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
303 {
304 m_vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer->object(), indexedIndirectOffset, 1, 0);
305 break;
306 }
307 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
308 {
309 m_vk.cmdDrawIndirectCount( cmdBuffer,
310 m_indirectBuffer->object(), indirectOffset,
311 m_indirectCountBuffer->object(), 0, 3,
312 sizeof(vk::VkDrawIndirectCommand));
313 break;
314 }
315 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
316 {
317 m_vk.cmdDrawIndexedIndirectCount(cmdBuffer,
318 m_indirectBuffer->object(), indexedIndirectOffset,
319 m_indirectCountBuffer->object(), 0, 3,
320 sizeof(vk::VkDrawIndexedIndirectCommand));
321 break;
322 }
323 default: DE_ASSERT(false);
324 }
325 }
326 }
327
iterate(void)328 tcu::TestStatus ConditionalDraw::iterate (void)
329 {
330 tcu::TestLog& log = m_context.getTestContext().getLog();
331 const vk::VkQueue queue = m_context.getUniversalQueue();
332 const vk::VkDevice device = m_context.getDevice();
333
334 const bool useSecondaryCmdBuffer = m_conditionalData.conditionInherited || m_conditionalData.conditionInSecondaryCommandBuffer;
335 beginRender(useSecondaryCmdBuffer ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE);
336
337 vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;
338
339 if (useSecondaryCmdBuffer)
340 {
341 const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
342 {
343 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
344 DE_NULL,
345 m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE // conditionalRenderingEnable
346 };
347
348 const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
349 {
350 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
351 &conditionalRenderingInheritanceInfo,
352 *m_renderPass, // renderPass
353 0u, // subpass
354 *m_framebuffer, // framebuffer
355 VK_FALSE, // occlusionQueryEnable
356 (vk::VkQueryControlFlags)0u, // queryFlags
357 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
358 };
359
360 const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
361 {
362 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
363 DE_NULL,
364 vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
365 &inheritanceInfo
366 };
367
368 m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo);
369
370 targetCmdBuffer = *m_secondaryCmdBuffer;
371 }
372
373 const vk::VkDeviceSize vertexBufferOffset = 0;
374 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
375
376 m_vk.cmdBindVertexBuffers(targetCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
377
378 switch(m_command)
379 {
380 case DRAW_COMMAND_TYPE_DRAW:
381 {
382 break;
383 }
384 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
385 {
386 createAndBindIndexBuffer(targetCmdBuffer);
387 break;
388 }
389 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
390 {
391 createIndirectBuffer();
392 break;
393 }
394 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
395 {
396 createAndBindIndexBuffer(targetCmdBuffer);
397 createIndexedIndirectBuffer();
398 break;
399 }
400 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
401 {
402 createIndirectBuffer();
403 createIndirectCountBuffer();
404 break;
405 }
406 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
407 {
408 createAndBindIndexBuffer(targetCmdBuffer);
409 createIndexedIndirectBuffer();
410 createIndirectCountBuffer();
411 break;
412 }
413 default: DE_ASSERT(false);
414 }
415
416 m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
417
418 m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
419
420 if (m_conditionalData.conditionInSecondaryCommandBuffer)
421 {
422 beginConditionalRendering(m_vk, *m_secondaryCmdBuffer, *m_conditionalBuffer, m_conditionalData);
423 recordDraw(*m_secondaryCmdBuffer);
424 m_vk.cmdEndConditionalRenderingEXT(*m_secondaryCmdBuffer);
425 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
426 }
427 else if (m_conditionalData.conditionInherited)
428 {
429 recordDraw(*m_secondaryCmdBuffer);
430 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
431 }
432
433 if (m_conditionalData.conditionInPrimaryCommandBuffer)
434 {
435 beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
436
437 if (m_conditionalData.conditionInherited)
438 {
439 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
440 }
441 else
442 {
443 recordDraw(*m_cmdBuffer);
444 }
445
446 m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
447 }
448 else if (useSecondaryCmdBuffer)
449 {
450 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
451 }
452
453 endRender();
454 endCommandBuffer(m_vk, *m_cmdBuffer);
455
456 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
457
458 // Validation
459 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
460 referenceFrame.allocLevel(0);
461
462 const deInt32 frameWidth = referenceFrame.getWidth();
463 const deInt32 frameHeight = referenceFrame.getHeight();
464
465 const tcu::Vec4 clearColor = tcu::RGBA::black().toVec();
466 const tcu::Vec4 drawColor = tcu::RGBA::blue().toVec();
467
468 tcu::clear(referenceFrame.getLevel(0), clearColor);
469
470 const tcu::Vec4 referenceColor = m_conditionalData.expectCommandExecution ?
471 drawColor : clearColor;
472
473 Draw::ReferenceImageCoordinates refCoords;
474
475 for (int y = 0; y < frameHeight; y++)
476 {
477 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
478
479 for (int x = 0; x < frameWidth; x++)
480 {
481 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
482
483 if ((yCoord >= refCoords.bottom &&
484 yCoord <= refCoords.top &&
485 xCoord >= refCoords.left &&
486 xCoord <= refCoords.right))
487 referenceFrame.getLevel(0).setPixel(referenceColor, x, y);
488 }
489 }
490
491 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
492 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
493 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
494
495 qpTestResult res = QP_TEST_RESULT_PASS;
496
497 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
498 referenceFrame.getLevel(0), renderedFrame, 0.05f,
499 tcu::COMPARE_LOG_RESULT))
500 {
501 res = QP_TEST_RESULT_FAIL;
502 }
503
504 return tcu::TestStatus(res, qpGetTestResultName(res));
505 }
506
507 } // anonymous
508
ConditionalDrawTests(tcu::TestContext & testCtx)509 ConditionalDrawTests::ConditionalDrawTests (tcu::TestContext &testCtx)
510 : TestCaseGroup (testCtx, "draw", "Conditional Rendering Of Draw Commands")
511 {
512 /* Left blank on purpose */
513 }
514
~ConditionalDrawTests(void)515 ConditionalDrawTests::~ConditionalDrawTests (void) {}
516
init(void)517 void ConditionalDrawTests::init (void)
518 {
519 for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
520 {
521 const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
522
523 tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "Conditionaly execute draw calls");
524
525 for (deUint32 commandTypeIdx = 0; commandTypeIdx < DRAW_COMMAND_TYPE_DRAW_LAST; ++commandTypeIdx)
526 {
527 const DrawCommandType command = DrawCommandType(commandTypeIdx);
528
529 ConditionalTestSpec testSpec;
530 testSpec.command = command;
531 testSpec.drawCalls = 4;
532 testSpec.conditionalData = conditionData;
533 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
534 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
535
536 conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalDraw>(m_testCtx, getDrawCommandTypeName(command), "", testSpec));
537 }
538
539 addChild(conditionalDrawRootGroup);
540 }
541 }
542
543 } // conditional
544 } // vkt
545