Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / conditional_rendering / vktConditionalDrawTests.cpp
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 "vkTypeUtil.hpp"
34
35 #include "tcuTestLog.hpp"
36 #include "tcuResource.hpp"
37 #include "tcuImageCompare.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuRGBA.hpp"
40
41 #include "vkDefs.hpp"
42 #include "vkCmdUtil.hpp"
43
44 namespace vkt
45 {
46 namespace conditional
47 {
48 namespace
49 {
50
51 enum DrawCommandType
52 {
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,
59
60         DRAW_COMMAND_TYPE_DRAW_LAST
61 };
62
63 const char* getDrawCommandTypeName (DrawCommandType command)
64 {
65         switch (command)
66         {
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);
74         }
75         return "";
76 }
77
78 struct ConditionalTestSpec : public Draw::TestSpecBase
79 {
80         DrawCommandType         command;
81         deUint32                        drawCalls;
82         ConditionalData         conditionalData;
83 };
84
85 class ConditionalDraw : public Draw::DrawTestsBaseClass
86 {
87 public:
88         typedef         ConditionalTestSpec     TestSpec;
89
90                                                                 ConditionalDraw                         (Context &context, ConditionalTestSpec testSpec);
91
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);
98
99 protected:
100                                 void                    createRenderPassWithClear       (void);
101
102         const DrawCommandType               m_command;
103         const deUint32                                  m_drawCalls;
104
105         const ConditionalData                   m_conditionalData;
106         de::SharedPtr<Draw::Buffer>             m_conditionalBuffer;
107
108         vk::Move<vk::VkCommandBuffer>   m_secondaryCmdBuffer;
109
110         std::vector<deUint32>               m_indexes;
111         de::SharedPtr<Draw::Buffer>             m_indexBuffer;
112
113         de::SharedPtr<Draw::Buffer>             m_indirectBuffer;
114         de::SharedPtr<Draw::Buffer>             m_indirectCountBuffer;
115
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;
119 };
120
121 void checkSupport(Context& context, DrawCommandType command)
122 {
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");
125 }
126
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)
136 {
137         checkConditionalRenderingCapabilities(context, m_conditionalData);
138         checkSupport(context, m_command);
139
140         const float minX = -0.3f;
141         const float maxX = 0.3f;
142         const float drawStep = 0.6f / static_cast<float>(m_drawCalls);
143
144         for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
145         {
146                 const float minY = minX + static_cast<float>(drawIdx) * drawStep;
147                 const float maxY = minY + drawStep;
148
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));
152
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));
156         }
157
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));
161
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));
165
166         for (deUint32 index = 0; index < m_data.size(); index++)
167         {
168                 m_indexes.push_back(index);
169         }
170
171         initialize();
172
173         DE_ASSERT(!(m_conditionalData.clearInRenderPass && m_conditionalData.conditionInSecondaryCommandBuffer));
174
175         if (m_conditionalData.clearInRenderPass)
176                 createRenderPassWithClear();
177
178         m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
179 }
180
181 void ConditionalDraw::createRenderPassWithClear (void)
182 {
183         const auto                                      device                                  = m_context.getDevice();
184         Draw::RenderPassCreateInfo      renderPassCreateInfo;
185
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));
194
195         const vk::VkAttachmentReference colorAttachmentReference
196         {
197                 0,
198                 vk::VK_IMAGE_LAYOUT_GENERAL
199         };
200
201         renderPassCreateInfo.addSubpass(Draw::SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
202                                                                                                                          0,
203                                                                                                                          0,
204                                                                                                                          DE_NULL,
205                                                                                                                          1,
206                                                                                                                          &colorAttachmentReference,
207                                                                                                                          DE_NULL,
208                                                                                                                          Draw::AttachmentReference(),
209                                                                                                                          0,
210                                                                                                                          DE_NULL));
211
212         m_rpWithClear = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
213
214         // Framebuffer.
215         std::vector<vk::VkImageView>                    colorAttachments                { *m_colorTargetView };
216         const Draw::FramebufferCreateInfo               framebufferCreateInfo   (*m_rpWithClear, colorAttachments, WIDTH, HEIGHT, 1);
217
218         m_fbWithClear = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
219 }
220
221 void ConditionalDraw::createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer)
222 {
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);
229
230         deUint8* indexBufferPtr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
231         deMemcpy(indexBufferPtr, &m_indexes[0], static_cast<size_t>(indexDataSize));
232
233         vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
234
235         const vk::VkBuffer indexBuffer = m_indexBuffer->object();
236         m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
237 }
238
239 void ConditionalDraw::createIndirectBuffer (void)
240 {
241         const vk::VkDrawIndirectCommand badDrawCommand =
242         {
243                 6u,                                     // vertexCount
244                 1u,                                     // instanceCount
245                 m_drawCalls * 6u,       // firstVertex
246                 0u                                      // firstInstance
247         };
248
249         std::vector<vk::VkDrawIndirectCommand> drawCommands;
250         for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
251         {
252                 const vk::VkDrawIndirectCommand goodDrawCommand =
253                 {
254                         6u,                             // vertexCount
255                         1u,                             // instanceCount
256                         6u * drawIdx,   // firstVertex
257                         0u                              // firstInstance
258                 };
259
260                 drawCommands.push_back(goodDrawCommand);
261                 // *Bad* commands should not be rendered by vkCmdDrawIndirectCountKHR
262                 drawCommands.push_back(badDrawCommand);
263                 drawCommands.push_back(badDrawCommand);
264         }
265
266         const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndirectCommand);
267
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);
274
275         deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
276         deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
277
278         vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
279 }
280
281 void ConditionalDraw::createIndexedIndirectBuffer (void)
282 {
283         const vk::VkDrawIndexedIndirectCommand badDrawCommand =
284         {
285                 6u,                                     // indexCount
286                 1u,                                     // instanceCount
287                 m_drawCalls * 6u,       // firstIndex
288                 0u,                                     // vertexOffset
289                 0u,                                     // firstInstance
290         };
291
292         std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
293         for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
294         {
295                 const vk::VkDrawIndexedIndirectCommand goodDrawCommand =
296                 {
297                         6u,                             // indexCount
298                         1u,                             // instanceCount
299                         6u * drawIdx,   // firstIndex
300                         0u,                             // vertexOffset
301                         0u,                             // firstInstance
302                 };
303
304                 drawCommands.push_back(goodDrawCommand);
305                 // *Bad* commands should not be rendered by vkCmdDrawIndexedIndirectCountKHR
306                 drawCommands.push_back(badDrawCommand);
307                 drawCommands.push_back(badDrawCommand);
308         }
309
310         const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
311
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);
318
319         deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
320         deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
321
322         vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
323 }
324
325 void ConditionalDraw::createIndirectCountBuffer (void)
326 {
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);
333
334         deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
335         *(deUint32*)(countBufferPtr) = 1;
336
337         vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
338 }
339
340 void ConditionalDraw::recordDraw(vk::VkCommandBuffer cmdBuffer)
341 {
342         for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
343         {
344                 /* Indirect buffer has next layout:
345                  * goodCommand badCommand badCommand goodCommand badCommand badCommand ...
346                  */
347                 const vk::VkDeviceSize indirectOffset = sizeof(vk::VkDrawIndirectCommand) * drawIdx * 3;
348                 const vk::VkDeviceSize indexedIndirectOffset = sizeof(vk::VkDrawIndexedIndirectCommand) * drawIdx * 3;
349                 switch (m_command)
350                 {
351                         case DRAW_COMMAND_TYPE_DRAW:
352                         {
353                                 m_vk.cmdDraw(cmdBuffer, 6, 1, 6 * drawIdx, 0);
354                                 break;
355                         }
356                         case DRAW_COMMAND_TYPE_DRAW_INDEXED:
357                         {
358                                 m_vk.cmdDrawIndexed(cmdBuffer, 6, 1, 6 * drawIdx, 0, 0);
359                                 break;
360                         }
361                         case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
362                         {
363                                 m_vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer->object(), indirectOffset, 1, 0);
364                                 break;
365                         }
366                         case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
367                         {
368                                 m_vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer->object(), indexedIndirectOffset, 1, 0);
369                                 break;
370                         }
371                         case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
372                         {
373                                 m_vk.cmdDrawIndirectCount(      cmdBuffer,
374                                                                                         m_indirectBuffer->object(), indirectOffset,
375                                                                                         m_indirectCountBuffer->object(), 0, 3,
376                                                                                         sizeof(vk::VkDrawIndirectCommand));
377                                 break;
378                         }
379                         case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
380                         {
381                                 m_vk.cmdDrawIndexedIndirectCount(cmdBuffer,
382                                                                                                  m_indirectBuffer->object(), indexedIndirectOffset,
383                                                                                                  m_indirectCountBuffer->object(), 0, 3,
384                                                                                                  sizeof(vk::VkDrawIndexedIndirectCommand));
385                                 break;
386                         }
387                         default: DE_ASSERT(false);
388                 }
389         }
390 }
391
392 tcu::TestStatus ConditionalDraw::iterate (void)
393 {
394         tcu::TestLog&           log                     = m_context.getTestContext().getLog();
395         const vk::VkQueue       queue           = m_context.getUniversalQueue();
396         const vk::VkDevice      device          = m_context.getDevice();
397
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());
400
401         m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
402
403         beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
404         preRenderBarriers();
405
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);
408
409         if (m_conditionalData.clearInRenderPass)
410         {
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);
414         }
415         else
416         {
417                 beginLegacyRender(*m_cmdBuffer, subpassContents);
418         }
419
420         vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;
421
422         if (useSecondaryCmdBuffer)
423         {
424                 const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
425                 {
426                         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
427                         DE_NULL,
428                         m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE       // conditionalRenderingEnable
429                 };
430
431                 const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
432                 {
433                         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
434                         &conditionalRenderingInheritanceInfo,
435                         *m_renderPass,                                                                                  // renderPass
436                         0u,                                                                                                                     // subpass
437                         *m_framebuffer,                                                                                 // framebuffer
438                         VK_FALSE,                                                                                                       // occlusionQueryEnable
439                         (vk::VkQueryControlFlags)0u,                                                            // queryFlags
440                         (vk::VkQueryPipelineStatisticFlags)0u,                                          // pipelineStatistics
441                 };
442
443                 const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
444                 {
445                         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
446                         DE_NULL,
447                         vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
448                         &inheritanceInfo
449                 };
450
451                 VK_CHECK(m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo));
452
453                 targetCmdBuffer = *m_secondaryCmdBuffer;
454         }
455
456         const vk::VkDeviceSize vertexBufferOffset = 0;
457         const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
458
459         m_vk.cmdBindVertexBuffers(targetCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
460
461         switch(m_command)
462         {
463                 case DRAW_COMMAND_TYPE_DRAW:
464                 {
465                         break;
466                 }
467                 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
468                 {
469                         createAndBindIndexBuffer(targetCmdBuffer);
470                         break;
471                 }
472                 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
473                 {
474                         createIndirectBuffer();
475                         break;
476                 }
477                 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
478                 {
479                         createAndBindIndexBuffer(targetCmdBuffer);
480                         createIndexedIndirectBuffer();
481                         break;
482                 }
483                 case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
484                 {
485                         createIndirectBuffer();
486                         createIndirectCountBuffer();
487                         break;
488                 }
489                 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
490                 {
491                         createAndBindIndexBuffer(targetCmdBuffer);
492                         createIndexedIndirectBuffer();
493                         createIndirectCountBuffer();
494                         break;
495                 }
496                 default: DE_ASSERT(false);
497         }
498
499         m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
500
501         if (m_conditionalData.conditionInSecondaryCommandBuffer)
502         {
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);
507         }
508         else if (m_conditionalData.conditionInherited)
509         {
510                 recordDraw(*m_secondaryCmdBuffer);
511                 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
512         }
513
514         if (m_conditionalData.conditionInPrimaryCommandBuffer)
515         {
516                 if (!m_conditionalData.clearInRenderPass)
517                         beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
518
519                 if (m_conditionalData.conditionInherited)
520                 {
521                         m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
522                 }
523                 else
524                 {
525                         recordDraw(*m_cmdBuffer);
526                 }
527
528                 if (!m_conditionalData.clearInRenderPass)
529                         m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
530         }
531         else if (useSecondaryCmdBuffer)
532         {
533                 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
534         }
535
536         if (m_conditionalData.clearInRenderPass)
537         {
538                 // Finish conditional rendering outside the render pass.
539                 vk::endRenderPass(m_vk, *m_cmdBuffer);
540                 m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
541         }
542         else
543         {
544                 endLegacyRender(*m_cmdBuffer);
545         }
546
547         endCommandBuffer(m_vk, *m_cmdBuffer);
548
549         submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
550
551         // Validation
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);
554
555         const deInt32 frameWidth        = referenceFrame.getWidth();
556         const deInt32 frameHeight       = referenceFrame.getHeight();
557
558         tcu::clear(referenceFrame.getLevel(0), clearColor);
559
560         const tcu::Vec4 drawColor               = tcu::RGBA::blue().toVec();
561         const tcu::Vec4 referenceColor  = m_conditionalData.expectCommandExecution ? drawColor : clearColor;
562
563         Draw::ReferenceImageCoordinates refCoords;
564
565         for (int y = 0; y < frameHeight; y++)
566         {
567                 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
568
569                 for (int x = 0; x < frameWidth; x++)
570                 {
571                         const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
572
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);
578                 }
579         }
580
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);
584
585         qpTestResult res = QP_TEST_RESULT_PASS;
586
587         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
588                 referenceFrame.getLevel(0), renderedFrame, 0.05f,
589                 tcu::COMPARE_LOG_RESULT))
590         {
591                 res = QP_TEST_RESULT_FAIL;
592         }
593
594         return tcu::TestStatus(res, qpGetTestResultName(res));
595 }
596
597 }       // anonymous
598
599 ConditionalDrawTests::ConditionalDrawTests (tcu::TestContext &testCtx)
600         : TestCaseGroup (testCtx, "draw", "Conditional Rendering Of Draw Commands")
601 {
602         /* Left blank on purpose */
603 }
604
605 ConditionalDrawTests::~ConditionalDrawTests (void) {}
606
607 void ConditionalDrawTests::init (void)
608 {
609         for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
610         {
611                 const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
612
613                 tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "Conditionaly execute draw calls");
614
615                 for (deUint32 commandTypeIdx = 0; commandTypeIdx < DRAW_COMMAND_TYPE_DRAW_LAST; ++commandTypeIdx)
616                 {
617                         const DrawCommandType   command = DrawCommandType(commandTypeIdx);
618
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";
625
626                         conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalDraw>(m_testCtx, getDrawCommandTypeName(command), "", testSpec));
627                 }
628
629                 addChild(conditionalDrawRootGroup);
630         }
631 }
632
633 }       // conditional
634 }       // vkt